From 85827275de7c434868e3c33b845f9579c0b384bb Mon Sep 17 00:00:00 2001 From: Aidan Feldman Date: Sat, 27 Aug 2016 22:24:57 -0400 Subject: [PATCH] create a NarrativeTable struct (broken) --- control/narrative_table.go | 38 +++++++++++++++++++++++++++++++++ control/narrative_table_test.go | 37 ++++++++++++++++++++++++++++++++ ssp/document.go | 28 ++++++++++++++++++++---- templater/templater.go | 28 +++++++++++++++++++++--- templater/templater_test.go | 13 +++++++++++ 5 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 control/narrative_table.go create mode 100644 control/narrative_table_test.go diff --git a/control/narrative_table.go b/control/narrative_table.go new file mode 100644 index 0000000..a66c773 --- /dev/null +++ b/control/narrative_table.go @@ -0,0 +1,38 @@ +package control + +import ( + "fmt" + + "github.com/jbowtie/gokogiri/xml" + "github.com/opencontrol/fedramp-templater/opencontrols" +) + +type NarrativeTable struct { + tbl table +} + +func NewNarrativeTable(root xml.Node) NarrativeTable { + tbl := table{Root: root} + return NarrativeTable{tbl} +} + +func (t *NarrativeTable) SectionRows() ([]xml.Node, error) { + // skip the header row + return t.tbl.searchSubtree(`.//w:tr[position() > 1]`) +} + +func (t *NarrativeTable) Fill(openControlData opencontrols.Data) (err error) { + control, err := t.tbl.controlName() + if err != nil { + return + } + // TODO remove hard-coding + sectionKey := "b" + + narrative := openControlData.GetNarrative(control, sectionKey) + fmt.Println(narrative) + + // TODO fill it in + + return +} diff --git a/control/narrative_table_test.go b/control/narrative_table_test.go new file mode 100644 index 0000000..315278d --- /dev/null +++ b/control/narrative_table_test.go @@ -0,0 +1,37 @@ +package control_test + +import ( + . "github.com/opencontrol/fedramp-templater/control" + "github.com/opencontrol/fedramp-templater/fixtures" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("NarrativeTable", func() { + Describe("SectionRows", func() { + It("returns the correct number for a singular narrative", func() { + doc := fixtures.LoadSSP("FedRAMP_ac-2-1_v2.1.docx") + defer doc.Close() + root, err := doc.NarrativeTable("AC-2 (1)") + Expect(err).NotTo(HaveOccurred()) + + table := NewNarrativeTable(root) + sections, err := table.SectionRows() + Expect(err).NotTo(HaveOccurred()) + Expect(len(sections)).To(Equal(1)) + }) + + It("returns the correct number for multiple narrative sections", func() { + doc := fixtures.LoadSSP("FedRAMP_ac-2_v2.1.docx") + defer doc.Close() + root, err := doc.NarrativeTable("AC-2") + Expect(err).NotTo(HaveOccurred()) + + table := NewNarrativeTable(root) + sections, err := table.SectionRows() + Expect(err).NotTo(HaveOccurred()) + Expect(len(sections)).To(Equal(11)) + }) + }) +}) diff --git a/ssp/document.go b/ssp/document.go index ba17b81..34cfe54 100644 --- a/ssp/document.go +++ b/ssp/document.go @@ -1,6 +1,8 @@ package ssp import ( + "fmt" + "github.com/jbowtie/gokogiri/xml" "github.com/opencontrol/doc-template/docx" "github.com/opencontrol/fedramp-templater/docx/helper" @@ -34,15 +36,33 @@ func Load(path string) (ssp *Document, err error) { } // SummaryTables returns the summary tables for the controls and the control enhancements. -func (s *Document) SummaryTables() (tables []xml.Node, err error) { +func (s *Document) SummaryTables() ([]xml.Node, error) { // find the tables matching the provided headers, ignoring whitespace return s.xmlDoc.Search("//w:tbl[contains(normalize-space(.), 'Control Summary') or contains(normalize-space(.), 'Control Enhancement Summary')]") } -// NarrativeTables returns the narrative tables for the controls and the control enhancements. -func (s *Document) NarrativeTables() (tables []xml.Node, err error) { +// to retrieve all narrative tables, pass in an empty string +func (s *Document) findNarrativeTables(control string) ([]xml.Node, error) { // find the tables matching the provided headers, ignoring whitespace - return s.xmlDoc.Search("//w:tbl[contains(normalize-space(.), 'What is the solution and how is it implemented?')]") + xpath := fmt.Sprintf("//w:tbl[contains(normalize-space(.), '%s What is the solution and how is it implemented?')]", control) + return s.xmlDoc.Search(xpath) + // TODO return NarrativeTables +} + +// NarrativeTables returns the narrative tables for the controls and the control enhancements. +func (s *Document) NarrativeTables() ([]xml.Node, error) { + return s.findNarrativeTables("") +} + +// NarrativeTables returns the narrative tables for the specified control or control enhancement. +func (s *Document) NarrativeTable(control string) (table xml.Node, err error) { + tables, err := s.findNarrativeTables(control) + if err != nil { + return + } + // TODO return error if there is more than one + table = tables[0] + return } // Content retrieves the text from within the Word document. diff --git a/templater/templater.go b/templater/templater.go index 3be9ccc..000ad38 100644 --- a/templater/templater.go +++ b/templater/templater.go @@ -7,8 +7,7 @@ import ( "github.com/opencontrol/fedramp-templater/ssp" ) -// TemplatizeSSP inserts OpenControl data into (i.e. modifies) the provided SSP. -func TemplatizeSSP(s *ssp.Document, openControlData opencontrols.Data) (err error) { +func fillSummaryTables(s *ssp.Document, openControlData opencontrols.Data) (err error) { tables, err := s.SummaryTables() if err != nil { return @@ -17,10 +16,33 @@ func TemplatizeSSP(s *ssp.Document, openControlData opencontrols.Data) (err erro ct := control.NewSummaryTable(table) err = ct.Fill(openControlData) if err != nil { - return err + return } } + return +} + +func fillNarrativeTables(s *ssp.Document, openControlData opencontrols.Data) (err error) { + tables, err := s.NarrativeTables() + if err != nil { + return + } + for _, table := range tables { + ct := control.NewNarrativeTable(table) + err = ct.Fill(openControlData) + if err != nil { + return + } + } + + return +} + +// TemplatizeSSP inserts OpenControl data into (i.e. modifies) the provided SSP. +func TemplatizeSSP(s *ssp.Document, openControlData opencontrols.Data) (err error) { + fillSummaryTables(s, openControlData) + fillNarrativeTables(s, openControlData) s.UpdateContent() return diff --git a/templater/templater_test.go b/templater/templater_test.go index e24393c..ced9493 100644 --- a/templater/templater_test.go +++ b/templater/templater_test.go @@ -32,6 +32,19 @@ var _ = Describe("Templater", func() { content := doc.Content() Expect(content).To(ContainSubstring(`Responsible Role: Amazon Elastic Compute Cloud: AWS Staff`)) }) + + It("fills in the narrative field", func() { + doc := fixtures.LoadSSP("FedRAMP_ac-2_v2.1.docx") + defer doc.Close() + openControlData := fixtures.LoadOpenControlFixture() + + err := TemplatizeSSP(doc, openControlData) + + Expect(err).NotTo(HaveOccurred()) + content := doc.Content() + Expect(content).To(ContainSubstring(`Justification in narrative form B for AC-2`)) + Expect(content).To(ContainSubstring(`Justification in narrative form for AC-2 (1)`)) + }) }) Describe("DiffSSP", func() {