Skip to content

Commit 77e9cd2

Browse files
committed
Merge branch 'master' into feature-testcases
# Conflicts: # sdpi-supplement/referenced-artifacts/sdpi-requirements.json
2 parents 9533e76 + 15d87d4 commit 77e9cd2

107 files changed

Lines changed: 12600 additions & 380 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
:: Creates html output for all tests. This should make
2+
:: all tests pass, but take care that the output generated
3+
:: is correct!
4+
5+
call build_test_result full_requirement
6+
call build_test_result ics_filtered
7+
call build_test_result ics_no_filter
8+
call build_test_result min_requirement
9+
call build_test_result profiles
10+
call build_test_result ref_ics_requirement
11+
call build_test_result ref_variables
12+
call build_test_result req-ownership
13+
call build_test_result risk_requirement
14+
call build_test_result test_level_input
15+
call build_test_result test_offset_input
16+
call build_test_result transaction-option
17+
call build_test_result transactions
18+
call build_test_result use_case
19+
call build_test_result use_case_option
20+
call build_test_result use_case_requirement
21+
call build_test_result content-module
22+
call build_test_result content-module-option
23+
call build_test_result cross_ref_requirement
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
gradlew.bat run --args="--input-file ../../asciidoc/sdpi-supplement.adoc --output-folder ../../sdpi-supplement --backend pdf"
2+
3+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
:: Creates html output file based on a test ascii doc.
2+
:: We leave off all the html headers to make the test more robust
3+
:: (that is, test don't depend on css in headers).
4+
5+
:: Argument: name of test ascii doc file in src/test/resources/
6+
7+
gradlew.bat run --args="--input-file src/test/resources/%1.adoc --output-folder src/test/resources --backend html --test"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
xcopy ..\..\asciidoc\css\*.* ..\..\sdpi-supplement\css /I /R /Y
2+
xcopy ..\..\asciidoc\fonts\*.* ..\..\sdpi-supplement\fonts /I /R /Y
3+
xcopy ..\..\asciidoc\images\*.* ..\..\sdpi-supplement\images /I /R /Y
4+
xcopy ..\..\asciidoc\js\*.* ..\..\sdpi-supplement\js /I /R /Y

.ci/asciidoc-converter/src/main/kotlin/org/sdpi/AsciidocConverter.kt

Lines changed: 183 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,77 +2,225 @@ package org.sdpi
22

33
import kotlinx.serialization.encodeToString
44
import kotlinx.serialization.json.Json
5+
import org.apache.logging.log4j.kotlin.logger
56
import org.asciidoctor.Asciidoctor
67
import org.asciidoctor.Options
78
import org.asciidoctor.SafeMode
89
import org.sdpi.asciidoc.extension.*
9-
import org.sdpi.asciidoc.github.Issues
1010
import java.io.File
1111
import java.io.OutputStream
1212
import java.nio.file.Files
1313
import java.nio.file.Path
14+
import kotlin.io.path.absolutePathString
15+
16+
/**
17+
* Options to configure AsciidocConverter.
18+
*/
19+
class ConverterOptions(
20+
/**
21+
* Token to access the GitHub api. For including issues
22+
* in the document output, for example.
23+
*/
24+
val githubToken: String? = null,
25+
26+
/**
27+
* Defines the target format for the document output. See
28+
* https://docs.asciidoctor.org/asciidoctorj/latest/asciidoctor-api-options/#backend
29+
* Typically "html" or "pdf"
30+
*/
31+
val outputFormat: String = "html",
32+
33+
/**
34+
* When true, document structure is written to the log stream
35+
* for diagnostics.
36+
*/
37+
val dumpStructure: Boolean = false,
38+
39+
/**
40+
* When true, the document output is simplified for unit
41+
* tests. For example, the style sheet is not included.
42+
*/
43+
val generateTestOutput: Boolean = false,
44+
45+
/**
46+
* Folder where extracts (requirements, use-cases, etc.) should
47+
* be placed. If null, the extracts won't be written.
48+
*/
49+
val extractsFolder: Path? = null,
50+
) {
51+
companion object {
52+
private const val DEFAULT_EXTRACTS_FOLDER: String = "referenced-artifacts"
53+
54+
fun makeDefaultPath(strOutputFolder: String): Path {
55+
return Path.of(strOutputFolder, DEFAULT_EXTRACTS_FOLDER)
56+
}
57+
}
58+
}
59+
1460

1561
class AsciidocConverter(
1662
private val inputType: Input,
17-
private val outputFile: File,
18-
private val githubToken: String?,
19-
private val mode: Mode = Mode.Productive,
63+
private val outputFile: OutputStream,
64+
private val conversionOptions: ConverterOptions,
2065
) : Runnable {
66+
67+
val anchorCollector = DocumentAnchorCollector()
68+
69+
fun documentAnchors() = anchorCollector.getKnownAnchors()
70+
71+
val bibliographyCollector = BibliographyCollector()
72+
val transactionActorsProcessor = TransactionActorsProcessor()
73+
val profileTransactionCollector = TransactionIncludeProcessor()
74+
val profileUseCaseCollector = UseCaseIncludeProcessor()
75+
val profileContentModuleCollector = ContentModuleIncludeProcessor()
76+
77+
val infoCollector = SdpiInformationCollector(
78+
bibliographyCollector,
79+
transactionActorsProcessor,
80+
profileTransactionCollector,
81+
profileUseCaseCollector,
82+
profileContentModuleCollector
83+
)
84+
2185
override fun run() {
2286
val options = Options.builder()
2387
.safe(SafeMode.UNSAFE)
24-
.backend(BACKEND)
88+
.backend(conversionOptions.outputFormat)
2589
.sourcemap(true)
26-
.toFile(outputFile).build()
90+
.headerFooter(!conversionOptions.generateTestOutput)
91+
.toStream(outputFile).build()
92+
val bEnablePrePostProcessing = true
2793

2894
val asciidoctor = Asciidoctor.Factory.create()
2995

3096
val anchorReplacements = AnchorReplacementsMap()
3197

32-
val requirementsBlockProcessor = RequirementsBlockProcessor()
33-
asciidoctor.javaExtensionRegistry().block(requirementsBlockProcessor)
34-
asciidoctor.javaExtensionRegistry().treeprocessor(
35-
NumberingProcessor(
36-
when (mode) {
37-
is Mode.Test -> mode.structureDump
38-
else -> null
39-
},
40-
anchorReplacements
41-
)
42-
)
43-
asciidoctor.javaExtensionRegistry().treeprocessor(RequirementLevelProcessor())
44-
asciidoctor.javaExtensionRegistry().preprocessor(IssuesSectionPreprocessor(githubToken))
45-
asciidoctor.javaExtensionRegistry().preprocessor(DisableSectNumsProcessor())
46-
asciidoctor.javaExtensionRegistry().preprocessor(ReferenceSanitizerPreprocessor(anchorReplacements))
47-
asciidoctor.javaExtensionRegistry()
48-
.postprocessor(ReferenceSanitizerPostprocessor(anchorReplacements))
98+
// Formats sdpi_requirement blocks & their content.
99+
// * RequirementBlockProcessor2 handles the containing sdpi_requirement block
100+
// * RelatedBlockProcessor handles [RELATED] blocks within requirement blocks.
101+
// * RequirementExampleBlockProcessor handles [EXAMPLE] blocks within requirement blocks.
102+
// * TransactionActorsProcessor handles definitions of actor contributions within
103+
// transaction sections.
104+
asciidoctor.javaExtensionRegistry().block(RequirementBlockProcessor2())
105+
asciidoctor.javaExtensionRegistry().block(RelatedBlockProcessor())
106+
asciidoctor.javaExtensionRegistry().block(RequirementExampleBlockProcessor())
107+
asciidoctor.javaExtensionRegistry().block(transactionActorsProcessor)
108+
109+
asciidoctor.javaExtensionRegistry().treeprocessor(NumberingProcessor(null, anchorReplacements))
110+
111+
// Gather bibliography entries.
112+
113+
asciidoctor.javaExtensionRegistry().treeprocessor(bibliographyCollector)
114+
115+
// Gather profiles, the transactions, use cases they include.
116+
asciidoctor.javaExtensionRegistry().blockMacro(profileTransactionCollector)
117+
118+
asciidoctor.javaExtensionRegistry().blockMacro(profileUseCaseCollector)
119+
120+
asciidoctor.javaExtensionRegistry().blockMacro(profileContentModuleCollector)
121+
122+
// Gather SDPI specific information from the document such as
123+
// requirements and use-cases.
124+
125+
asciidoctor.javaExtensionRegistry().treeprocessor(infoCollector)
126+
127+
// Gather anchors in the document so we can verify there aren't any invalid links.
128+
asciidoctor.javaExtensionRegistry().treeprocessor(anchorCollector)
129+
130+
// Support to insert tables of requirements etc. sdpi_requirement_table macros.
131+
// Block macro processors insert placeholders that are populated when the tree is ready.
132+
// Tree processors fill in the placeholders.
133+
asciidoctor.javaExtensionRegistry().blockMacro(AddRequirementQueryPlaceholder())
134+
asciidoctor.javaExtensionRegistry().blockMacro(AddICSPlaceholder())
135+
asciidoctor.javaExtensionRegistry().blockMacro(AddTransactionQueryPlaceholder())
136+
asciidoctor.javaExtensionRegistry().blockMacro(AddContentModuleQueryPlaceholder())
137+
138+
asciidoctor.javaExtensionRegistry().treeprocessor(PopulateTables(infoCollector))
139+
140+
// Handle inline macros to cross-reference information from the document tree.
141+
asciidoctor.javaExtensionRegistry().inlineMacro(RequirementReferenceMacroProcessor(infoCollector))
142+
asciidoctor.javaExtensionRegistry().inlineMacro(UseCaseReferenceMacroProcessor(infoCollector))
143+
asciidoctor.javaExtensionRegistry().inlineMacro(ActorReferenceMacroProcessor(infoCollector))
144+
asciidoctor.javaExtensionRegistry().inlineMacro(ContentModuleReferenceMacroProcessor(infoCollector))
145+
asciidoctor.javaExtensionRegistry().inlineMacro(TransactionReferenceMacroProcessor(infoCollector))
146+
asciidoctor.javaExtensionRegistry().inlineMacro(ProfileReferenceMacroProcessor(infoCollector))
147+
148+
if (bEnablePrePostProcessing) {
149+
asciidoctor.javaExtensionRegistry().preprocessor(IssuesSectionPreprocessor(conversionOptions.githubToken))
150+
asciidoctor.javaExtensionRegistry().preprocessor(DisableSectNumsProcessor())
151+
}
152+
153+
if (bEnablePrePostProcessing) {
154+
println("Enable pre post processing.")
155+
val referenceSanitizerPre = ReferenceSanitizerPreprocessor(anchorReplacements)
156+
asciidoctor.javaExtensionRegistry().preprocessor(referenceSanitizerPre)
157+
if (conversionOptions.outputFormat == "html") {
158+
// Post processor not supported for PDFs
159+
// https://docs.asciidoctor.org/asciidoctorj/latest/extensions/postprocessor/
160+
asciidoctor.javaExtensionRegistry().postprocessor(ReferenceSanitizerPostprocessor(anchorReplacements))
161+
}
162+
}
163+
164+
// Dumps tree of document structure to stdio.
165+
// Best not to use for very large documents!
166+
// Note: enabling this breaks variable replacement for {var_transaction_id}. Unclear why.
167+
if (conversionOptions.dumpStructure) {
168+
asciidoctor.javaExtensionRegistry().treeprocessor(DumpTreeInfo())
169+
}
49170

50171
asciidoctor.requireLibrary("asciidoctor-diagram") // enables plantuml
172+
51173
when (inputType) {
52174
is Input.FileInput -> asciidoctor.convertFile(inputType.file, options)
53175
is Input.StringInput -> asciidoctor.convert(inputType.string, options)
54176
}
55177

178+
//profileTransactionCollector.dump()
179+
//anchorReplacements.dump()
180+
//anchorCollector.dumpKnownAnchors()
181+
182+
if (conversionOptions.extractsFolder != null) {
183+
val jsonFormatter = Json {
184+
prettyPrint = true
185+
explicitNulls = false
186+
}
187+
188+
writeArtifact(
189+
"sdpi-profiles",
190+
jsonFormatter.encodeToString(infoCollector.profiles())
191+
)
192+
writeArtifact(
193+
"sdpi-use-cases",
194+
jsonFormatter.encodeToString(infoCollector.useCases())
195+
)
196+
writeArtifact(
197+
"sdpi-content-modules",
198+
jsonFormatter.encodeToString(infoCollector.contentModules().values)
199+
)
200+
writeArtifact(
201+
"sdpi-transactions",
202+
jsonFormatter.encodeToString(infoCollector.transactions().values)
203+
)
204+
writeArtifact(
205+
"sdpi-requirements",
206+
jsonFormatter.encodeToString(infoCollector.requirements().values)
207+
)
208+
}
209+
56210
asciidoctor.shutdown()
57211

58-
val referencedArtifactsName = "referenced-artifacts"
59-
val path = Path.of(outputFile.parentFile.absolutePath, referencedArtifactsName)
60-
Files.createDirectories(path)
61-
val reqsDump = Json.encodeToString(requirementsBlockProcessor.detectedRequirements())
62-
Path.of(path.toFile().absolutePath, "sdpi-requirements.json").toFile().writeText(reqsDump)
63212
}
64213

65-
private companion object {
66-
const val BACKEND = "html"
214+
private fun writeArtifact(strArtifactName: String, strArtifact: String) {
215+
if (conversionOptions.extractsFolder != null) {
216+
Files.createDirectories(conversionOptions.extractsFolder)
217+
Path.of(conversionOptions.extractsFolder.absolutePathString(), "${strArtifactName}.json").toFile()
218+
.writeText(strArtifact)
219+
}
67220
}
68221

69222
sealed interface Input {
70223
data class FileInput(val file: File) : Input
71224
data class StringInput(val string: String) : Input
72225
}
73-
74-
sealed interface Mode {
75-
object Productive : Mode
76-
data class Test(val structureDump: OutputStream) : Mode
77-
}
78226
}

.ci/asciidoc-converter/src/main/kotlin/org/sdpi/ConvertAndVerifySupplement.kt

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package org.sdpi
22

33
import com.github.ajalt.clikt.core.CliktCommand
4-
import com.github.ajalt.clikt.parameters.options.default
5-
import com.github.ajalt.clikt.parameters.options.option
6-
import com.github.ajalt.clikt.parameters.options.required
7-
import com.github.ajalt.clikt.parameters.options.validate
4+
import com.github.ajalt.clikt.parameters.options.*
85
import com.github.ajalt.clikt.parameters.types.choice
96
import com.github.ajalt.clikt.parameters.types.file
107
import org.apache.logging.log4j.kotlin.Logging
118
import org.sdpi.asciidoc.AsciidocErrorChecker
12-
import org.sdpi.asciidoc.github.IssueImport
139
import java.io.File
1410
import kotlin.system.exitProcess
1511

16-
fun main(args: Array<String>) = ConvertAndVerifySupplement().main(args
12+
fun main(args: Array<String>) = ConvertAndVerifySupplement().main(
13+
args
1714
// when (System.getenv().containsKey("CI")) {
1815
// true -> args.firstOrNull()?.split(" ") ?: listOf() // caution: blanks in quotes not covered here!
1916
// false -> args.toList()
@@ -47,6 +44,12 @@ class ConvertAndVerifySupplement : CliktCommand("convert-supplement") {
4744

4845
private val githubToken by option("--github-token", help = "Github token to request issues")
4946

47+
private val dumpStructure by option("--dump-structure", help = "Writes document tree to std-out during processing")
48+
.flag(default = false)
49+
50+
private val testGenerator by option("--test", help = "Writes document without headers for test output")
51+
.flag(default = false)
52+
5053
override fun run() {
5154
runCatching {
5255
val asciidocErrorChecker = AsciidocErrorChecker()
@@ -59,14 +62,25 @@ class ConvertAndVerifySupplement : CliktCommand("convert-supplement") {
5962

6063
logger.info { "Write output to '${outFile.canonicalPath}'" }
6164

62-
AsciidocConverter(AsciidocConverter.Input.FileInput(adocInputFile), outFile, githubToken).run()
65+
val converter = AsciidocConverter(
66+
AsciidocConverter.Input.FileInput(adocInputFile),
67+
outFile.outputStream(),
68+
ConverterOptions(
69+
githubToken = githubToken,
70+
extractsFolder = ConverterOptions.makeDefaultPath(outputFolder.absolutePath),
71+
outputFormat = backend,
72+
dumpStructure = dumpStructure,
73+
generateTestOutput = testGenerator,
74+
)
75+
)
76+
converter.run()
6377

64-
asciidocErrorChecker.run()
78+
asciidocErrorChecker.run(converter.documentAnchors().keys.toList())
6579

6680
logger.info { "File successfully written" }
6781
}.onFailure {
6882
logger.error { it.message }
69-
logger.trace(it) { it.message }
83+
//logger.trace(it) { it.message }
7084
exitProcess(1)
7185
}
7286
}

0 commit comments

Comments
 (0)