public void AddTable(string title, Table customTable, string bookmark = null, string caption = "Table ") { // Add a caption for the table if (!string.IsNullOrEmpty(title)) { Paragraph p3 = DocHelper.CreateTableCaption( tableCount++, title, bookmark, caption, this.hyperlinkTracker); this.documentBody.AppendChild(p3); } this.documentBody.Append(customTable); this.documentBody.Append( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.BlankLinkText }))); // Blank line added for spacing to next para }
private void AddValueSetDetailTable(ValueSet valueSet, DateTime bindingDate) { string valueSetIdentifier = valueSet.GetIdentifier(this.igTypePlugin); string bookmarkId = this.GetValueSetBookmark(valueSet); List <ValueSetMember> members = valueSet.GetActiveMembers(bindingDate); if (members == null || members.Count == 0) { return; } TableCell headingCell = new TableCell( new TableCellProperties() { GridSpan = new GridSpan() { Val = 4 } }, new Paragraph( new ParagraphProperties(new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun( string.Format("Value Set: {0} {1}", valueSet.Name, valueSet.GetIdentifier(igTypePlugin))))); if (!string.IsNullOrEmpty(valueSet.Description)) { headingCell.Append( new Paragraph( new ParagraphProperties(new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(valueSet.Description))); } if (!string.IsNullOrEmpty(valueSet.Source)) { headingCell.Append( new Paragraph( new ParagraphProperties(new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun("Value Set Source: "), this.hyperlinkTracker.CreateUrlHyperlink(this.mainPart, valueSet.Source, valueSet.Source, Properties.Settings.Default.LinkStyle))); } TableRow headerRow = DocHelper.CreateTableHeader("Code", "Code System", "Code System OID", "Print Name"); List <TableCell> headerCells = headerRow.ChildElements.OfType <TableCell>().ToList(); headerCells[0].ChildElements.OfType <TableCellProperties>().First().TableCellWidth = new TableCellWidth() { Width = "1560" }; headerCells[1].ChildElements.OfType <TableCellProperties>().First().TableCellWidth = new TableCellWidth() { Width = "3000" }; headerCells[2].ChildElements.OfType <TableCellProperties>().First().TableCellWidth = new TableCellWidth() { Width = "3000" }; headerCells[3].ChildElements.OfType <TableCellProperties>().First().TableCellWidth = new TableCellWidth() { Width = "2520" }; Table t = DocHelper.CreateTable( new TableRow(headingCell), headerRow); int maximumMembers = this.defaultMaxMembers; if (this.valueSetMaximumMembers != null && this.valueSetMaximumMembers.ContainsKey(valueSetIdentifier)) { maximumMembers = this.valueSetMaximumMembers[valueSetIdentifier]; } int count = 0; foreach (ValueSetMember currentMember in members) { if (count >= maximumMembers) { break; } TableRow memberRow = new TableRow( new TableCell( new TableCellProperties() { TableCellWidth = new TableCellWidth() { Width = "1170" } }, new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(currentMember.Code))), new TableCell( new TableCellProperties() { TableCellWidth = new TableCellWidth() { Width = "3195" } }, new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(currentMember.CodeSystem.Name))), new TableCell( new TableCellProperties() { TableCellWidth = new TableCellWidth() { Width = "3195" } }, new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(currentMember.CodeSystem.Oid))), new TableCell( new TableCellProperties() { TableCellWidth = new TableCellWidth() { Width = "2520" } }, new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(currentMember.DisplayName))) ); t.Append(memberRow); count++; } if (count <= members.Count - 1 || valueSet.IsIncomplete) { TableRow moreMembersRow = new TableRow( new TableCell( new TableCellProperties() { GridSpan = new GridSpan() { Val = 4 } }, new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun("...")))); t.Append(moreMembersRow); } this.tables.AddTable(valueSet.Name, t, bookmarkId); }
/// <summary> /// Adds a single template to the implementation guide document. /// </summary> /// <param name="template">The template to add to the document</param> private void AddTemplate(Template template) { Log.For(this).Trace("BEGIN: Adding template '{0}'.", template.Oid); List <TemplateConstraint> templateConstraints = (from tc in this._tdb.TemplateConstraints where tc.TemplateId == template.Id select tc).ToList(); List <TemplateConstraint> rootConstraints = templateConstraints .Where(y => y.ParentConstraintId == null) .OrderBy(y => y.Order) .ToList(); GreenTemplate greenTemplate = template.GreenTemplates.FirstOrDefault(); string bookmarkId = template.Bookmark; string templateIdentifier = string.Format("identifier: {0}", template.Oid); if (!string.IsNullOrEmpty(template.PrimaryContext)) { templateIdentifier = string.Format("{0} (identifier: {1})", template.PrimaryContext, template.Oid); } this.templateCount++; string headingLevel = Properties.Settings.Default.TemplateHeaderStyle; if (exportSettings.AlphaHierarchicalOrder && template.ImpliedTemplateId != null && this.templates.Exists(y => y.Id == template.ImpliedTemplateId)) { headingLevel = Properties.Settings.Default.TemplateHeaderSecondLevelStyle; } StringBuilder lTitleBuilder = new StringBuilder(string.Format("{0}", template.Name.Substring(1))); bool lDirectlyOwnedTemplate = template.OwningImplementationGuideId == this.implementationGuide.Id; bool lStatusMatches = template.StatusId == template.OwningImplementationGuide.PublishStatusId; string lTemplateTitle = lTitleBuilder.ToString(); // Output the title of the template Paragraph pHeading = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = headingLevel })); this.hyperlinkTracker.AddAnchorAround(pHeading, bookmarkId, new Run( new Text(template.Name.Substring(0, 1))), new Run( new Text(lTemplateTitle))); if (!string.IsNullOrEmpty(template.Notes) && this.exportSettings.IncludeNotes) { this.commentManager.AddCommentRange(pHeading, template.Notes); } this.document.MainDocumentPart.Document.Body.AppendChild(pHeading); // Output the "bracket data" for the template string detailsText = string.Format("identifier: {0} ({1})", template.Oid, template.IsOpen == true ? "open" : "closed"); if (!string.IsNullOrEmpty(template.PrimaryContext)) { detailsText = string.Format("[{0}: identifier {1} ({2})]", template.PrimaryContext, template.Oid, template.IsOpen == true ? "open" : "closed"); } Paragraph pDetails = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TemplateLocationStyle }), DocHelper.CreateRun(detailsText)); this.document.MainDocumentPart.Document.Body.AppendChild(pDetails); //Output IG publish/draft info with "bracket data" format if (exportSettings.IncludeTemplateStatus) { string status = template.Status != null ? template.Status.Status : "Draft"; string igText = string.Format("{0} as part of {1}", status, template.OwningImplementationGuide.GetDisplayName()); Paragraph igDetails = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TemplateLocationStyle }), DocHelper.CreateRun(igText)); this.document.MainDocumentPart.Document.Body.AppendChild(igDetails); } // If we were told to generate context tables for the template... if (exportSettings.GenerateTemplateContextTable) { TemplateContextTable.AddTable(this._tdb, this.templateRelationships, this.tables, this.document.MainDocumentPart.Document.Body, template, this.templates, this.hyperlinkTracker); } // Output the template's descriptionz if (!string.IsNullOrEmpty(template.Description)) { OpenXmlElement element = template.Description.MarkdownToOpenXml(this._tdb, this.document.MainDocumentPart); OpenXmlHelper.Append(element, this.document.MainDocumentPart.Document.Body); } // If we were told to generate tables for the template... if (exportSettings.GenerateTemplateConstraintTable) { this.constraintTableGenerator.AddTemplateConstraintTable(this.schema, template, this.document.MainDocumentPart.Document.Body, templateIdentifier); } if (templateConstraints.Count(y => y.IsHeading) > 0) { Paragraph propertiesHeading = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.PropertiesHeadingStyle }), DocHelper.CreateRun("Properties")); this.document.MainDocumentPart.Document.Body.AppendChild(propertiesHeading); } // Output the implied template conformance line if (template.ImpliedTemplate != null) { OpenXmlElement templateReference = !this.templates.Contains(template.ImpliedTemplate) ? (OpenXmlElement)DocHelper.CreateRun(template.ImpliedTemplate.Name) : (OpenXmlElement)this.hyperlinkTracker.CreateHyperlink(template.ImpliedTemplate.Name, template.ImpliedTemplate.Bookmark, Properties.Settings.Default.LinkStyle); Paragraph impliedConstraint = new Paragraph( new ParagraphProperties( new NumberingProperties( new NumberingLevelReference() { Val = 0 }, new NumberingId() { Val = GenerationConstants.BASE_TEMPLATE_INDEX + (int)template.Id })), DocHelper.CreateRun("Conforms to "), templateReference, DocHelper.CreateRun(" template "), DocHelper.CreateRun("(identifier: " + template.ImpliedTemplate.Oid + ")", style: Properties.Settings.Default.TemplateOidStyle), DocHelper.CreateRun(".")); this.document.MainDocumentPart.Document.Body.Append(impliedConstraint); } bool lCreateValueSetTables = exportSettings.DefaultValueSetMaxMembers > 0; IConstraintGenerator constraintGenerator = ConstraintGenerationFactory.NewConstraintGenerator( this.igSettings, this.document.MainDocumentPart, this.commentManager, this.figures, exportSettings.IncludeXmlSamples, _tdb, rootConstraints, templateConstraints, template, this.templates, Properties.Settings.Default.ConstraintHeadingStyle, exportSettings.SelectedCategories, this.hyperlinkTracker); constraintGenerator.GenerateConstraints(lCreateValueSetTables, this.exportSettings.IncludeNotes); // Add value-set tables if (lCreateValueSetTables) { var constraintValueSets = (from c in templateConstraints where c.ValueSet != null select new { ValueSet = c.ValueSet, ValueSetDate = c.ValueSetDate }) .Distinct(); foreach (var cConstraintValueSet in constraintValueSets) { DateTime?bindingDate = cConstraintValueSet.ValueSetDate != null ? cConstraintValueSet.ValueSetDate : this.implementationGuide.PublishDate; if (bindingDate == null) { bindingDate = DateTime.Now; } this.valueSetsExport.AddValueSet(cConstraintValueSet.ValueSet, bindingDate.Value); } } if (exportSettings.IncludeXmlSamples) { foreach (var lSample in template.TemplateSamples.OrderBy(y => y.Id)) { this.figures.AddSample(lSample.Name, lSample.XmlSample); } } Log.For(this).Trace("END: Adding template '{0}' with {1} constraints.", template.Oid, templateConstraints.Count); }
private void LoadDifferencesAsAppendix(string aIgName, List <IGDifferenceViewModel> aDifferences) { // Create the heading for the appendix Paragraph heading = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TemplateTypeHeadingStyle }), new Run( new Text("Changes from Previous Version"))); this.document.MainDocumentPart.Document.Body.AppendChild(heading); foreach (IGDifferenceViewModel lDifference in aDifferences) { Paragraph changeHeadingPara = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TemplateHeaderStyle }), DocHelper.CreateRun(lDifference.TemplateName)); this.document.MainDocumentPart.Document.Body.AppendChild(changeHeadingPara); OpenXmlElement templateTitleElement = DocHelper.CreateRun(string.Format("{0} ({1})", lDifference.TemplateName, lDifference.TemplateOid)); if (lDifference.ShouldLink) { templateTitleElement = this.hyperlinkTracker.CreateHyperlink( string.Format("{0} ({1})", lDifference.TemplateName, lDifference.TemplateOid), lDifference.TemplateBookmark, Properties.Settings.Default.LinkStyle); } Paragraph changeLinkPara = new Paragraph( new ParagraphProperties(new KeepNext()), templateTitleElement, new Run( new Break())); this.document.MainDocumentPart.Document.Body.AppendChild(changeLinkPara); Table t = this.tables.AddTable(null, new string[] { "Change", "Old", "New" }); // Show template field changes first foreach (ComparisonFieldResult lResult in lDifference.Difference.ChangedFields) { TableRow memberRow = new TableRow( new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(lResult.Name))), new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(lResult.Old))), new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(lResult.New))) ); t.Append(memberRow); } // Show constraint changes second foreach (ComparisonConstraintResult lConstraintChange in lDifference.Difference.ChangedConstraints) { if (lConstraintChange.Type == CompareStatuses.Unchanged) { continue; } TableRow memberRow = new TableRow( new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(string.Format("CONF #: {0} {1}", lConstraintChange.Number, lConstraintChange.Type)))), new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(lConstraintChange.OldNarrative))), new TableCell( new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(lConstraintChange.NewNarrative))) ); t.Append(memberRow); } } }
/// <summary> /// Adds a table for the template in question which lists all constraints in separate rows. /// </summary> public void AddTemplateConstraintTable(SimpleSchema schema, Template template, Body documentBody, string templateXpath) { var constraintCategories = template.ChildConstraints.Where(y => !string.IsNullOrEmpty(y.Category)).Select(y => y.Category).Distinct(); var includeCategoryHeader = false; if (!this.HasSelectedCategories && constraintCategories.Count() > 0) { includeCategoryHeader = true; } else if (this.HasSelectedCategories && this.selectedCategories.Count > 1) { includeCategoryHeader = true; } var rootConstraints = template.ChildConstraints.Where(y => y.ParentConstraintId == null); List <HeaderDescriptor> lHeaders = new List <HeaderDescriptor>(); if (includeCategoryHeader) { lHeaders.Add(new HeaderDescriptor() { HeaderName = CATEGORY, AutoResize = true, AutoWrap = false, ColumnWidth = "720" }); } lHeaders.Add(new HeaderDescriptor() { HeaderName = XPATH, AutoResize = true, AutoWrap = false, ColumnWidth = "3345" }); lHeaders.Add(new HeaderDescriptor() { HeaderName = CARD, AutoResize = false, CellWidth = .5, ColumnWidth = "720" }); lHeaders.Add(new HeaderDescriptor() { HeaderName = VERB, AutoResize = false, CellWidth = .8, ColumnWidth = "1152" }); lHeaders.Add(new HeaderDescriptor() { HeaderName = DATA_TYPE, AutoResize = false, CellWidth = .6, ColumnWidth = "864" }); lHeaders.Add(new HeaderDescriptor() { HeaderName = CONF, AutoResize = false, CellWidth = .6, ColumnWidth = "1104" }); lHeaders.Add(new HeaderDescriptor() { HeaderName = FIXED_VALUE, AutoResize = false, CellWidth = .6, ColumnWidth = "2975" }); Table t = this.tables.AddTable(string.Format("{0} Constraints Overview", template.Name), lHeaders.ToArray()); TableRow templateRow = new TableRow( new TableCell( new TableCellProperties( new GridSpan() { Val = new Int32Value(includeCategoryHeader ? 7 : 6) }), new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle }), DocHelper.CreateRun(templateXpath)))); t.Append(templateRow); var templateSchema = schema.GetSchemaFromContext(template.PrimaryContextType); var constraintIds = template.ChildConstraints.Select(y => y.Id).ToList(); var templateReferences = (from r in this.references join tc in constraintIds on r.TemplateConstraintId equals tc select r); // Start out creating the first set of rows with root (top-level) constraints (constraints that don't have children) foreach (TemplateConstraint cConstraint in rootConstraints.OrderBy(y => y.Order)) { if (this.HasSelectedCategories && !string.IsNullOrEmpty(cConstraint.Category) && !this.selectedCategories.Contains(cConstraint.Category)) { continue; } var schemaObject = templateSchema != null?templateSchema.Children.SingleOrDefault(y => y.Name == cConstraint.Context) : null; this.AddTemplateTableConstraint(template, templateReferences, t, cConstraint, 1, includeCategoryHeader, schemaObject); } }
private void Generate() { Table table = this.CreateTable(); var documentTemplates = this.templates.Where(y => y.PrimaryContextType == "ClinicalDocument").OrderBy(y => y.Name); var sectionTemplates = this.templates.Where(y => y.PrimaryContextType == "Section").OrderBy(y => y.Name); foreach (var documentTemplate in documentTemplates) { TableRow row = new TableRow(new TableRowProperties()); table.Append(row); TableCell docTypeCell = new TableCell(new TableCellProperties()); row.Append(docTypeCell); Paragraph docTypePara = new Paragraph(); docTypeCell.Append(docTypePara); this.hyperlinkTracker.AddHyperlink(docTypePara, documentTemplate.Name, documentTemplate.Bookmark, Properties.Settings.Default.LinkStyle); docTypePara.Append(new Break(), DocHelper.CreateRun(documentTemplate.Oid)); var requiredSections = (from tc in documentTemplate.ChildConstraints join tcr in this.tdb.TemplateConstraintReferences on tc.Id equals tcr.TemplateConstraintId join st in this.templates on tcr.ReferenceIdentifier equals st.Oid join ptc in documentTemplate.ChildConstraints on tc.ParentConstraintId equals ptc.Id where tc.Context == "section" && tcr.ReferenceType == ConstraintReferenceTypes.Template && ptc.Context == "component" && (ptc.Conformance == "SHALL" || ptc.Conformance == "SHALL NOT") select st).ToList(); var optionalSections = (from tc in documentTemplate.ChildConstraints join tcr in this.tdb.TemplateConstraintReferences on tc.Id equals tcr.TemplateConstraintId join st in this.templates on tcr.ReferenceIdentifier equals st.Oid join ptc in documentTemplate.ChildConstraints on tc.ParentConstraintId equals ptc.Id where tc.Context == "section" && tcr.ReferenceType == ConstraintReferenceTypes.Template && ptc.Context == "component" && (ptc.Conformance.StartsWith("SHOULD") || ptc.Conformance.StartsWith("MAY")) select st).ToList(); TableCell requiredSectionsCell = new TableCell(new TableCellProperties()); row.Append(requiredSectionsCell); Paragraph requiredSectionsPara = new Paragraph(); requiredSectionsCell.Append(requiredSectionsPara); for (int i = 0; i < requiredSections.Count; i++) { this.hyperlinkTracker.AddHyperlink(requiredSectionsPara, requiredSections[i].Name, requiredSections[i].Bookmark, Properties.Settings.Default.LinkStyle); if (i != requiredSections.Count - 1) { requiredSectionsPara.Append(new Break()); } } if (requiredSections.Count == 0) { requiredSectionsPara.Append(DocHelper.CreateRun("N/A")); } TableCell optionalSectionsCell = new TableCell(new TableCellProperties()); row.Append(optionalSectionsCell); Paragraph optionalSectionsPara = new Paragraph(); optionalSectionsCell.Append(optionalSectionsPara); for (int i = 0; i < optionalSections.Count; i++) { this.hyperlinkTracker.AddHyperlink(optionalSectionsPara, optionalSections[i].Name, optionalSections[i].Bookmark, Properties.Settings.Default.LinkStyle); if (i != optionalSections.Count - 1) { optionalSectionsPara.Append(new Break()); } } if (optionalSections.Count == 0) { optionalSectionsPara.Append(DocHelper.CreateRun("N/A")); } } }
/// <summary> /// Adds a context table for the template. The context table lists all templates that are used by the current template, as /// well as all templates that this current template uses. Templates that use this template also indicate whether they are /// required or optional, depending on the conformance of the constraint that uses this template. /// </summary> /// <param name="template">The template in question</param> /// <param name="allConstraints">All constraints for the current template</param> private void AddTemplateContextTable() { TableRow newRow = new TableRow(); TableCell usedByCell = new TableCell(); TableCell containedCell = new TableCell(); List <int> exportedTemplateIds = this.exportedTemplates.Select(y => y.Id).ToList(); string templateIdentifier = template.Oid; int templateId = template.Id; var usedByTemplates = (from tr in this.relationships where tr.ChildTemplateId == template.Id select new { Name = tr.ParentTemplateName, Bookmark = tr.ParentTemplateBookmark, Required = tr.Required }).Distinct().ToList(); var containedTemplates = (from tr in this.relationships where tr.ParentTemplateId == template.Id select new { Name = tr.ChildTemplateName, Bookmark = tr.ChildTemplateBookmark, Required = tr.Required }).Distinct().ToList(); int maxRows = containedTemplates.Count > usedByTemplates.Count ? containedTemplates.Count : usedByTemplates.Count; for (int i = 0; i < maxRows; i++) { Paragraph usedByPara = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle })); Paragraph containedPara = new Paragraph( new ParagraphProperties( new ParagraphStyleId() { Val = Properties.Settings.Default.TableContentStyle })); var usedByTemplateReference = i < usedByTemplates.Count ? usedByTemplates[i] : null; var containedTemplateReference = i < containedTemplates.Count ? containedTemplates[i] : null; // Output the used by template if (usedByTemplateReference != null) { usedByPara.Append( this.hyperlinkTracker.CreateHyperlink(usedByTemplateReference.Name, usedByTemplateReference.Bookmark, Properties.Settings.Default.TableLinkStyle), DocHelper.CreateRun(usedByTemplateReference.Required ? " (required)" : " (optional)")); usedByCell.Append(usedByPara); } // Output the contained template if (containedTemplateReference != null) { containedPara.Append( this.hyperlinkTracker.CreateHyperlink(containedTemplateReference.Name, containedTemplateReference.Bookmark, Properties.Settings.Default.TableLinkStyle), DocHelper.CreateRun(containedTemplateReference.Required ? " (required)" : " (optional)")); containedCell.Append(containedPara); } } // Make sure the cells have at least one paragraph in them if (containedCell.ChildElements.Count == 0) { containedCell.AppendChild(new Paragraph()); } if (usedByCell.ChildElements.Count == 0) { usedByCell.AppendChild(new Paragraph()); } // Only add the table to the document if there are conatined or used-by relationships if (maxRows > 0) { string[] headers = new string[] { TEMPLATE_CONTEXT_TABLE_USED_BY, TEMPLATE_CONTEXT_TABLE_CONTAINS }; Table t = this.tables.AddTable(string.Format("{0} Contexts", template.Name), headers); t.Append( new TableRow(usedByCell, containedCell)); } }
private void Generate() { Table table = this.CreateTable(); var documentTemplates = this.templates.Where(y => y.TemplateTypeId == this.documentTemplateTypeId).OrderBy(y => y.Name); foreach (var documentTemplate in documentTemplates) { TableRow row = new TableRow(new TableRowProperties()); table.Append(row); TableCell docTypeCell = new TableCell(new TableCellProperties()); row.Append(docTypeCell); Paragraph docTypePara = new Paragraph(); docTypeCell.Append(docTypePara); this.hyperlinkTracker.AddHyperlink(docTypePara, documentTemplate.Name, documentTemplate.Bookmark, Properties.Settings.Default.LinkStyle); docTypePara.Append(new Break(), DocHelper.CreateRun(documentTemplate.Oid)); var sectionsConstraints = (from tc in documentTemplate.ChildConstraints join tcr in this.tdb.TemplateConstraintReferences on tc.Id equals tcr.TemplateConstraintId join st in this.templates on tcr.ReferenceIdentifier equals st.Oid join ptc in documentTemplate.ChildConstraints on tc.ParentConstraintId equals ptc.Id where tcr.ReferenceType == ConstraintReferenceTypes.Template && st.TemplateTypeId == this.sectionTemplateTypeId select new { Constraint = tc, Template = st }); List <Template> requiredSections = new List <Template>(); List <Template> optionalSections = new List <Template>(); foreach (var sectionConstraint in sectionsConstraints) { bool isRequiredAtTopLevel = sectionConstraint.Constraint.ParentConstraintId == null && sectionConstraint.Constraint.IsRequiredConformance(); bool isRequiredByParent = sectionConstraint.Constraint.ParentConstraintId != null && sectionConstraint.Constraint.ParentConstraint.HasRequiredParent(); if (isRequiredAtTopLevel || isRequiredByParent) { requiredSections.Add(sectionConstraint.Template); } else { optionalSections.Add(sectionConstraint.Template); } } TableCell requiredSectionsCell = new TableCell(new TableCellProperties()); row.Append(requiredSectionsCell); Paragraph requiredSectionsPara = new Paragraph(); requiredSectionsCell.Append(requiredSectionsPara); for (int i = 0; i < requiredSections.Count; i++) { this.hyperlinkTracker.AddHyperlink(requiredSectionsPara, requiredSections[i].Name, requiredSections[i].Bookmark, Properties.Settings.Default.LinkStyle); if (i != requiredSections.Count - 1) { requiredSectionsPara.Append(new Break()); } } if (requiredSections.Count == 0) { requiredSectionsPara.Append(DocHelper.CreateRun("N/A")); } TableCell optionalSectionsCell = new TableCell(new TableCellProperties()); row.Append(optionalSectionsCell); Paragraph optionalSectionsPara = new Paragraph(); optionalSectionsCell.Append(optionalSectionsPara); for (int i = 0; i < optionalSections.Count; i++) { this.hyperlinkTracker.AddHyperlink(optionalSectionsPara, optionalSections[i].Name, optionalSections[i].Bookmark, Properties.Settings.Default.LinkStyle); if (i != optionalSections.Count - 1) { optionalSectionsPara.Append(new Break()); } } if (optionalSections.Count == 0) { optionalSectionsPara.Append(DocHelper.CreateRun("N/A")); } } }