public string Compose(RequirementSpecification data) { var markdown = string.Empty; markdown += $"# {data.Title}\n"; foreach (var upperRequirement in data.Requirements) { markdown += $"\n## [{upperRequirement.ID}]{upperRequirement.Summary}\n"; markdown += $"\n### 理由\n\n{upperRequirement.Reason}\n"; markdown += $"\n### 説明\n\n{upperRequirement.Description}\n"; foreach (var lowerRequirement in upperRequirement.Requirements) { markdown += $"\n### [{lowerRequirement.ID}]{lowerRequirement.Summary}\n"; markdown += $"\n#### 理由\n\n{lowerRequirement.Reason}\n"; markdown += $"\n#### 説明\n\n{lowerRequirement.Description}\n"; markdown += "\n#### 仕様\n"; foreach (var group in lowerRequirement.SpecificationGroups) { markdown += $"\n<{group.Category}>\n"; if (group.Specifications.Any()) { markdown += "\n"; } foreach (var specification in group.Specifications) { var check = specification.IsImplemented ? "x" : " "; markdown += $"* [{check}] [{specification.ID}]{specification.Description}\n"; } } } } return(markdown); }
/// <summary> /// Parse a markdown document /// </summary> /// <param name="content">The markdown text</param> /// <returns></returns> public RequirementSpecification Parse(string content) { _document.Parse(content); status = UsdmScope.None; var data = new RequirementSpecification(); foreach (var element in _document.Blocks) { switch (element.Type) { case MarkdownBlockType.Header: AnalyzeHeader(element, data); break; case MarkdownBlockType.Paragraph: AnalyzeParagraph(element, data); break; case MarkdownBlockType.List: AnalyzeList(element, data); break; default: Console.WriteLine($"Type: {element.Type}"); Console.WriteLine(element.ToString()); break; } } return(data); }
private void AnalyzeParagraph(MarkdownBlock element, RequirementSpecification data) { var item = data.Requirements.Last(); switch (status) { case UsdmScope.UpperRequiremetReason: item.Reason += element.ToString() ?? string.Empty; break; case UsdmScope.UpperRequiremetDescription: item.Description += element.ToString() ?? string.Empty; break; case UsdmScope.LowerRequiremetReason: item.Requirements.Last().Reason += element.ToString() ?? string.Empty; break; case UsdmScope.LowerRequiremetDescription: item.Requirements.Last().Description += element.ToString() ?? string.Empty; break; case UsdmScope.Specification: var rawString = element.ToString(); if (rawString != null) { item.Requirements.Last() .SpecificationGroups.Add( new SpecificationGroup { Category = ParseUtility.ExtractGroupCategory(rawString) } ); } break; default: Console.WriteLine($"Type: {element.Type}"); Console.WriteLine(element.ToString()); break; } }
private void AnalyzeList(MarkdownBlock element, RequirementSpecification data) { switch (status) { case UsdmScope.UpperRequiremetReason: data.Requirements.Last().Reason += "\n" + element.ToString() ?? string.Empty; break; case UsdmScope.UpperRequiremetDescription: data.Requirements.Last().Description += "\n" + element.ToString() ?? string.Empty; break; case UsdmScope.LowerRequiremetReason: data.Requirements.Last().Requirements.Last().Reason += "\n" + element.ToString() ?? string.Empty; break; case UsdmScope.LowerRequiremetDescription: data.Requirements.Last().Requirements.Last().Description += "\n" + element.ToString() ?? string.Empty; break; case UsdmScope.Specification: var listBlock = element as ListBlock; if (listBlock != null) { data.Requirements.Last() .Requirements.Last() .SpecificationGroups.Last() .Specifications.AddRange( ParseUtility.DecomposeSpecification(listBlock) ); } break; default: Console.WriteLine($"Type: {element.Type}"); Console.WriteLine(element.ToString()); break; } }
public void DecomposeHeadingCorrectly() { var data = new RequirementSpecification { Title = "title", Requirements = new List <UpperRequirement>() { new UpperRequirement { ID = "REQ01", Summary = "requirement1", Reason = "reason1", Description = "description1", Requirements = new List <LowerRequirement>() { new LowerRequirement { ID = "REQ01-01", Summary = "requirement1-1", Reason = "reason1-1", Description = "description1-1", SpecificationGroups = new List <SpecificationGroup>() { new SpecificationGroup { Category = "group", Specifications = new List <Specification>() { new Specification { IsImplemented = false, ID = "SPC01-01-01", Description = "description1" }, new Specification { IsImplemented = true, ID = "SPC01-01-02", Description = "description2" } } } } } } } }, }; var target = new ExcelDecoder(); var book = target.Decode(data); var sheet = book.GetSheet("title"); Assert.Equal("要求", sheet.GetRow(0).GetCell(0).StringCellValue); Assert.Equal("REQ01", sheet.GetRow(0).GetCell(1).StringCellValue); Assert.Equal("requirement1", sheet.GetRow(0).GetCell(2).StringCellValue); Assert.Equal("理由", sheet.GetRow(1).GetCell(1).StringCellValue); Assert.Equal("reason1", sheet.GetRow(1).GetCell(2).StringCellValue); Assert.Equal("説明", sheet.GetRow(2).GetCell(1).StringCellValue); Assert.Equal("要求", sheet.GetRow(3).GetCell(1).StringCellValue); Assert.Equal("REQ01-01", sheet.GetRow(3).GetCell(2).StringCellValue); Assert.Equal("requirement1-1", sheet.GetRow(3).GetCell(3).StringCellValue); Assert.Equal("理由", sheet.GetRow(4).GetCell(2).StringCellValue); Assert.Equal("reason1-1", sheet.GetRow(4).GetCell(3).StringCellValue); Assert.Equal("説明", sheet.GetRow(5).GetCell(2).StringCellValue); Assert.Equal("description1-1", sheet.GetRow(5).GetCell(3).StringCellValue); Assert.Equal("<group>", sheet.GetRow(6).GetCell(2).StringCellValue); Assert.Equal("□", sheet.GetRow(7).GetCell(1).StringCellValue); Assert.Equal("SPC01-01-01", sheet.GetRow(7).GetCell(2).StringCellValue); Assert.Equal("description1", sheet.GetRow(7).GetCell(3).StringCellValue); Assert.Equal("■", sheet.GetRow(8).GetCell(1).StringCellValue); Assert.Equal("SPC01-01-02", sheet.GetRow(8).GetCell(2).StringCellValue); Assert.Equal("description2", sheet.GetRow(8).GetCell(3).StringCellValue); }
private void AnalyzeHeader(MarkdownBlock element, RequirementSpecification data) { var header = element as HeaderBlock; if (header != null) { var text = header.ToString().Trim(); switch (header.HeaderLevel) { case 1: data.Title = text; break; case 2: { var info = ParseUtility.DecomposeHeading(header); data.Requirements.Add( new UpperRequirement { ID = info.id, Summary = info.summary } ); } break; case 3: if (text.Equals("理由")) { status = UsdmScope.UpperRequiremetReason; } else if (text.Equals("説明")) { status = UsdmScope.UpperRequiremetDescription; } else { var info = ParseUtility.DecomposeHeading(header); data.Requirements.Last().Requirements.Add( new LowerRequirement { ID = info.id, Summary = info.summary } ); } break; case 4: if (text.Equals("理由")) { status = UsdmScope.LowerRequiremetReason; } else if (text.Equals("説明")) { status = UsdmScope.LowerRequiremetDescription; } else if (text.Equals("仕様")) { status = UsdmScope.Specification; } break; default: Console.WriteLine($"Text: {text}"); Console.WriteLine($"Level: {header.HeaderLevel}"); Console.WriteLine(element.ToString()); status = UsdmScope.None; break; } } }
public void ComposeCorrectly() { var expect = @"# title ## [REQ01]requirement1 ### 理由 reason1 ### 説明 description1 ### [REQ01-01]requirement1-1 #### 理由 reason1-1 #### 説明 description1-1 #### 仕様 <group> * [ ] [SPC01-01-01]description1 * [x] [SPC01-01-02]description2 "; var data = new RequirementSpecification { Title = "title", Requirements = new List <UpperRequirement>() { new UpperRequirement { ID = "REQ01", Summary = "requirement1", Reason = "reason1", Description = "description1", Requirements = new List <LowerRequirement>() { new LowerRequirement { ID = "REQ01-01", Summary = "requirement1-1", Reason = "reason1-1", Description = "description1-1", SpecificationGroups = new List <SpecificationGroup>() { new SpecificationGroup { Category = "group", Specifications = new List <Specification>() { new Specification { IsImplemented = false, ID = "SPC01-01-01", Description = "description1" }, new Specification { IsImplemented = true, ID = "SPC01-01-02", Description = "description2" } } } } } } } }, }; var target = new MarkdownComposer(); var actual = target.Compose(data); Assert.Equal(expect, actual); }
public IWorkbook Decode(RequirementSpecification data) { var book = new XSSFWorkbook(); book.CreateSheet(data.Title); var font = book.CreateFont(); font.FontName = "Yu Gothic Medium"; var headingStyle = CreateHeadingCellStyle(book, font); var upperHeadingStyle = CreateUpperHeadingCellStyle(book, font); var mediumHeadingStyle = CreateMediumHeadingCellStyle(book, font); var lowerHeadingStyle = CreateLowerHeadingCellStyle(book, font); var baseStyle = CreateBasicCellStyle(book, font); var itemStyle = CreateItemCellStyle(book, font); var sheet = book.GetSheet(data.Title); var rowIndex = 0; foreach (var element in data.Requirements) { // 上位要求の項目の作成 WriteCell(sheet, 0, rowIndex, "要求"); WriteCell(sheet, 1, rowIndex, element.ID); WriteCell(sheet, 2, rowIndex, element.Summary); sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 2, 3)); WriteStyle(sheet, 0, rowIndex, upperHeadingStyle); WriteStyle(sheet, 1, rowIndex, upperHeadingStyle); WriteStyle(sheet, 2, rowIndex, headingStyle); WriteStyle(sheet, 3, rowIndex, headingStyle); rowIndex++; // 上位要求の理由の作成 WriteCell(sheet, 1, rowIndex, "理由"); WriteCell(sheet, 2, rowIndex, element.Reason); sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 2, 3)); WriteStyle(sheet, 0, rowIndex, mediumHeadingStyle); WriteStyle(sheet, 1, rowIndex, itemStyle); WriteStyle(sheet, 2, rowIndex, baseStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); rowIndex++; // 上位要求の説明の作成 WriteCell(sheet, 1, rowIndex, "説明"); WriteCell(sheet, 2, rowIndex, element.Description); sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 2, 3)); WriteStyle(sheet, 0, rowIndex, lowerHeadingStyle); WriteStyle(sheet, 1, rowIndex, itemStyle); WriteStyle(sheet, 2, rowIndex, baseStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); rowIndex++; foreach (var item in element.Requirements) { // 下位要求の項目の作成 WriteCell(sheet, 1, rowIndex, "要求"); WriteCell(sheet, 2, rowIndex, item.ID); WriteCell(sheet, 3, rowIndex, item.Summary); WriteStyle(sheet, 1, rowIndex, upperHeadingStyle); WriteStyle(sheet, 2, rowIndex, upperHeadingStyle); WriteStyle(sheet, 3, rowIndex, headingStyle); rowIndex++; // 下位要求の理由の作成 WriteCell(sheet, 2, rowIndex, "理由"); WriteCell(sheet, 3, rowIndex, item.Reason); WriteStyle(sheet, 1, rowIndex, mediumHeadingStyle); WriteStyle(sheet, 2, rowIndex, itemStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); rowIndex++; // 下位要求の説明の作成 WriteCell(sheet, 2, rowIndex, "説明"); WriteCell(sheet, 3, rowIndex, item.Description); WriteStyle(sheet, 1, rowIndex, lowerHeadingStyle); WriteStyle(sheet, 2, rowIndex, itemStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); rowIndex++; foreach (var group in item.SpecificationGroups) { // 仕様グループの作成 WriteCell(sheet, 2, rowIndex, $"<{group.Category}>"); WriteStyle(sheet, 1, rowIndex, baseStyle); WriteStyle(sheet, 2, rowIndex, baseStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 2, 3)); rowIndex++; foreach (var spec in group.Specifications) { // 仕様の記述 WriteCell(sheet, 1, rowIndex, spec.IsImplemented ? "■" : "□"); WriteCell(sheet, 2, rowIndex, spec.ID); WriteCell(sheet, 3, rowIndex, spec.Description); WriteStyle(sheet, 1, rowIndex, baseStyle); WriteStyle(sheet, 2, rowIndex, baseStyle); WriteStyle(sheet, 3, rowIndex, baseStyle); rowIndex++; } } } } sheet.AutoSizeColumn(0); sheet.AutoSizeColumn(1); sheet.AutoSizeColumn(2); sheet.SetColumnWidth(3, 256 * 87 - ( sheet.GetColumnWidth(0) + sheet.GetColumnWidth(1) + sheet.GetColumnWidth(2) )); sheet.PrintSetup.PaperSize = 9; return(book); }
public RequirementSpecification Encode(IWorkbook book) { var result = new RequirementSpecification(); var sheet = book.GetSheetAt(0); result.Title = sheet.SheetName; var rowIndex = 0; var row = sheet.GetRow(rowIndex); while (row != null) { var cell = row.GetCell(0); if (cell != null) { var label = cell.StringCellValue; if (label.Equals("要求")) { var id = row.GetCell(1).StringCellValue; var summary = row.GetCell(2).StringCellValue; row = sheet.GetRow(++rowIndex); var reason = row.GetCell(2).StringCellValue; row = sheet.GetRow(++rowIndex); var description = row.GetCell(2).StringCellValue; result.Requirements.Add(new UpperRequirement { ID = id, Summary = summary, Reason = reason, Description = description, }); } else { throw new UsdmFormatException($"Unknown label: {label}"); } } else { cell = row.GetCell(1); if (cell != null) { var label = cell.StringCellValue; if (label.Equals("要求")) { var id = row.GetCell(2).StringCellValue; var summary = row.GetCell(3).StringCellValue; row = sheet.GetRow(++rowIndex); var reason = row.GetCell(3).StringCellValue; row = sheet.GetRow(++rowIndex); var description = row.GetCell(3).StringCellValue; result.Requirements.Last() .Requirements.Add(new LowerRequirement { ID = id, Summary = summary, Reason = reason, Description = description, }); } else if (label.Equals(string.Empty)) { var category = row.GetCell(2).StringCellValue; result.Requirements.Last() .Requirements.Last() .SpecificationGroups.Add( new SpecificationGroup { Category = ParseUtility.ExtractGroupCategory(category) } ); } else if (label.Equals("■") || label.Equals("□")) { var isImplemented = label.Equals("■"); var id = row.GetCell(2).StringCellValue; var description = row.GetCell(3).StringCellValue; result.Requirements.Last() .Requirements.Last() .SpecificationGroups.Last() .Specifications.Add( new Specification { IsImplemented = isImplemented, ID = id, Description = description } ); } else { throw new UsdmFormatException($"Unknown sublabel: {label}"); } } } row = sheet.GetRow(++rowIndex); } return(result); }