<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div>
<blockquote type="cite" class="">
<div class="">
<div class="WordSection1" style="page: WordSection1; caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<div class="">
<div style="margin: 0cm 0cm 0cm 36pt; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
Let me propose an experiment: take the existing ClassPrinter implementation — still monolithic — and try refactoring to use internal “printable models”, where the keys in the output (e.g., “class name”) are derived from the keys in the printable model, rather
than hard-coded format strings, and see how we like that? That should be a small step, and if we like it, we can take another step. If it turns out that is nastier to do that I am guessing, we can back off an think of another approach.<o:p class=""></o:p></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class=""><o:p class=""> </o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class="">I’m not quite how it would look like.<span class="Apple-converted-space"> </span><o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class="">This is one fragment of the actual templates in one format:<o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""> <span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(51, 107, 221);" class="">new</span><span style="font-size: 10pt; font-family: "Courier New";" class=""><span class="Apple-converted-space"> </span>Block(</span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">",%n <span class="Apple-converted-space"> </span><b class="">\"</b>module<b class="">\"</b>:
{%n <span class="Apple-converted-space"> </span><b class="">\"</b>name<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,%n <span class="Apple-converted-space"> </span><b class="">\"</b>flags<b class="">\"</b>:
%s,%n <span class="Apple-converted-space"> </span><b class="">\"</b>version<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,%n <span class="Apple-converted-space"> </span><b class="">\"</b>uses<b class="">\"</b>:
%s"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">" }"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">),</span></div>
</div>
</div>
</div>
</blockquote>
<div><br class="">
</div>
<div>Right. So first, the words like “module” and “name” can be derived from the keys in the Map. We have latitude here, but let’s say for example that the key is “class name” and in JSON this is rendered as “class name” and in XML as “<class-name>”. These
are both mechanical translations. That gets all of the text out of the format, and carries the name in the Map instead. Note also that all of the format specifiers are %s, since we’ve already converted the leaves of the Map to String. So much of these format
strings can be generated from the data itself. </div>
<div><br class="">
</div>
<div>Second, in the code you have, there is an implicit alignment between the order of the arguments to “formatted” and the order of the format specifiers, as is natural for formatters. But we can break this, by using a LinkedHashMap (which preserves order)
for the keys to ensure they come out in the right order. </div>
<div><br class="">
</div>
<div>Third, the block/table structure (with its prefix and suffix) can be derived from the shape of the Map. Instead of calling printTable, the key “requires” maps to a LIST of { “name” -> name, “flags” -> flags, “version” -> version }. This alone is enough
to trigger generation of an object whose key is “requires”, and whose corresponding value is an array of objects with name, flags, and version keys (and similar for other formats.). </div>
<div><br class="">
</div>
<br class="">
<blockquote type="cite" class="">
<div class="">
<div class="WordSection1" style="page: WordSection1; caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<div class="">
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""><o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""> <span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(51, 107, 221);" class="">new</span><span style="font-size: 10pt; font-family: "Courier New";" class=""><span class="Apple-converted-space"> </span>Table(</span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">",%n <span class="Apple-converted-space"> </span><b class="">\"</b>requires<b class="">\"</b>:
["</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"]"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"%n
{<span class="Apple-converted-space"> </span><b class="">\"</b>name<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,<span class="Apple-converted-space"> </span><b class="">\"</b>flags<b class="">\"</b>:
%s,<span class="Apple-converted-space"> </span><b class="">\"</b>version<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b><span class="Apple-converted-space"> </span>}"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">),<o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""> <span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(51, 107, 221);" class="">new</span><span style="font-size: 10pt; font-family: "Courier New";" class=""><span class="Apple-converted-space"> </span>Table(</span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">",%n <span class="Apple-converted-space"> </span><b class="">\"</b>exports<b class="">\"</b>:
["</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"]"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"%n
{<span class="Apple-converted-space"> </span><b class="">\"</b>package<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,<span class="Apple-converted-space"> </span><b class="">\"</b>flags<b class="">\"</b>:
%s,<span class="Apple-converted-space"> </span><b class="">\"</b>to<b class="">\"</b>: %s }"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">),<o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""> <span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(51, 107, 221);" class="">new</span><span style="font-size: 10pt; font-family: "Courier New";" class=""><span class="Apple-converted-space"> </span>Table(</span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">",%n <span class="Apple-converted-space"> </span><b class="">\"</b>opens<b class="">\"</b>:
["</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"]"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"%n
{<span class="Apple-converted-space"> </span><b class="">\"</b>package<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,<span class="Apple-converted-space"> </span><b class="">\"</b>flags<b class="">\"</b>:
%s,<span class="Apple-converted-space"> </span><b class="">\"</b>to<b class="">\"</b>: %s }"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">),<o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif; background-color: white;" class="">
<span style="font-size: 10pt; font-family: "Courier New";" class=""> <span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(51, 107, 221);" class="">new</span><span style="font-size: 10pt; font-family: "Courier New";" class=""><span class="Apple-converted-space"> </span>Table(</span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">",%n <span class="Apple-converted-space"> </span><b class="">\"</b>provides<b class="">\"</b>:
["</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"]"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">,<span class="Apple-converted-space"> </span></span><span style="font-size: 10pt; font-family: "Courier New"; color: rgb(30, 147, 71);" class="">"%n
{<span class="Apple-converted-space"> </span><b class="">\"</b>class<b class="">\"</b>:<span class="Apple-converted-space"> </span><b class="">\"</b>%s<b class="">\"</b>,<span class="Apple-converted-space"> </span><b class="">\"</b>with<b class="">\"</b>:
%s }"</span><span style="font-size: 10pt; font-family: "Courier New";" class="">),<o:p class=""></o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class="">While applied are following way:<o:p class=""></o:p></span></div>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> </span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">case</span></span><span style="" class=""> ModuleAttribute ma -> {<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> </span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">out</span></span><span style="" class="">.accept(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">module</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">header</span></span><span style="" class="">.formatted(ma.moduleName().name().stringValue(), quoteFlags(ma.moduleFlags()), ma.moduleVersion().map(Utf8Entry::stringValue).orElse(</span><span class="string"><span style="color: rgb(30, 147, 71);" class="">""</span></span><span style="" class="">), typesToString(ma.uses().stream().map(ce -> ce.asInternalName()))));<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> printTable(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">requires</span></span><span style="" class="">, ma.requires(), req -> </span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">new</span></span><span style="" class=""> Object[] {req.requires().name().stringValue(), quoteFlags(req.requiresFlags()), req.requiresVersion().map(Utf8Entry::stringValue).orElse(</span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">null</span></span><span style="" class="">)});<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> printTable(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">exports</span></span><span style="" class="">, ma.exports(), exp -> </span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">new</span></span><span style="" class=""> Object[] {exp.exportedPackage().name().stringValue(), quoteFlags(exp.exportsFlags()), typesToString(exp.exportsTo().stream().map(me -> me.name().stringValue()))});<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> printTable(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">opens</span></span><span style="" class="">, ma.opens(), open -> </span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">new</span></span><span style="" class=""> Object[] {open.openedPackage().name().stringValue(), quoteFlags(open.opensFlags()), typesToString(open.opensTo().stream().map(me -> me.name().stringValue()))});<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> printTable(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">provides</span></span><span style="" class="">, ma.provides(), provide -> </span><span class="literal"><span style="color: rgb(51, 107, 221);" class="">new</span></span><span style="" class=""> Object[] {provide.provides().asInternalName(), typesToString(provide.providesWith().stream().map(me -> me.asInternalName()))});<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> </span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">out</span></span><span style="" class="">.accept(</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">template</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">module</span></span><span style="" class="">.</span><span class="st0"><span style="color: rgb(206, 84, 184);" class="">footer</span></span><span style="" class="">.formatted());<o:p class=""></o:p></span></pre>
<pre style="margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; background-color: white;" class=""><span style="" class=""> }<o:p class=""></o:p></span></pre>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class=""><o:p class=""> </o:p></span></div>
<div style="margin: 0cm; font-size: 11pt; font-family: Calibri, sans-serif;" class="">
<span lang="EN-US" class="">Each individual parameter of each template has its position (the same position in each format) and format-specific escaping methods are frequently (and individually based on context) called. How do you suggest to pass it through
generic key-value maps, when String format is index-based?</span></div>
</div>
</div>
</div>
</blockquote>
<br class="">
</div>
<div>Control the order of keys in a Map with LHM; then just spool out the key-value pairs in order. </div>
<div><br class="">
</div>
<div><br class="">
</div>
<br class="">
</body>
</html>