poussecafe.doc.HtmlWriter Maven / Gradle / Ivy
The newest version!
package poussecafe.doc;
import freemarker.template.Configuration;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import org.apache.commons.io.IOUtils;
import poussecafe.doc.model.Aggregate;
import poussecafe.doc.model.DocumentationItem;
import poussecafe.doc.model.Domain;
import poussecafe.doc.model.Module;
import poussecafe.doc.model.UbiquitousLanguageEntry;
import poussecafe.doc.model.UbiquitousLanguageFactory;
import poussecafe.doc.model.domainprocessdoc.DomainProcessGraphNode;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
public class HtmlWriter {
public void writeHtml(Domain domain) {
try(var stream = new FileWriter(new File(outputDirectoryPath, "index.html"))) {
copyCss();
var freemarkerConfig = new Configuration(Configuration.VERSION_2_3_28);
freemarkerConfig.setClassForTemplateLoading(getClass(), "/");
var template = freemarkerConfig.getTemplate("index.html");
HashMap domainMap = new HashMap<>();
domainMap.put("name", domain.name());
domainMap.put("version", domain.version());
domainMap.put("modules",
domain.modules()
.stream()
.filter(module -> !module.isEmpty())
.sorted(this::compareModules)
.map(item -> adapt(item, domain))
.collect(toList()));
HashMap model = new HashMap<>();
model.put("includeGenerationDate", includeGenerationDate);
model.put("domain", domainMap);
model.put("generationDate", new Date());
model.put("ubiquitousLanguage",
ubitquitousLanguageFactory
.buildUbiquitousLanguage(domain)
.stream()
.filter(doc -> !doc.componentDoc().description().trivial())
.map(this::adapt)
.collect(toList()));
template.process(model, stream);
} catch (Exception e) {
throw new RuntimeException("Error while writing HTML", e);
}
}
private String outputDirectoryPath;
private boolean includeGenerationDate;
private int compareModules(Module moduleDoc1, Module moduleDoc2) {
DocumentationItem doc1 = moduleDoc1.documentation();
DocumentationItem doc2 = moduleDoc2.documentation();
return compareTo(doc1, doc2);
}
private int compareTo(DocumentationItem componentDoc1,
DocumentationItem componentDoc2) {
return componentDoc1.name().compareTo(componentDoc2.name());
}
private HashMap adapt(Module module, Domain domain) {
HashMap view = new HashMap<>();
DocumentationItem moduleDoc = module.documentation();
view.put("id", moduleDoc.id());
view.put("name", moduleDoc.name());
view.put("description", moduleDoc.description().description().orElse(""));
view.put("aggregates", module.aggregates()
.stream()
.filter(aggregate -> !aggregate.documentation().description().trivial())
.sorted(this::compareAggregates)
.map(this::adapt)
.collect(toList()));
view.put("services", module.services()
.stream()
.filter(doc -> !doc.description().trivial())
.sorted(this::compareTo)
.map(this::adapt)
.collect(toList()));
view.put("domainProcesses", module.processes()
.stream()
.filter(doc -> !doc.description().trivial())
.sorted(this::compareTo)
.map(item -> adaptDomainProcess(item, domain))
.collect(toList()));
return view;
}
private int compareAggregates(Aggregate aggregateDoc1, Aggregate aggregateDoc2) {
var doc1 = aggregateDoc1.documentation();
var doc2 = aggregateDoc2.documentation();
return compareTo(doc1, doc2);
}
private HashMap adapt(Aggregate aggregate) {
HashMap view = new HashMap<>();
var aggregateDoc = aggregate.documentation();
view.put("id", aggregateDoc.id());
view.put("name", aggregateDoc.name());
view.put("description", aggregateDoc.description().description().orElse(""));
view.put("entities", aggregate.entities().stream()
.filter(doc -> !doc.description().trivial())
.sorted(this::compareTo)
.map(this::adapt)
.collect(toList()));
view.put("valueObjects", aggregate.valueObjects().stream()
.filter(doc -> !doc.description().trivial())
.sorted(this::compareTo)
.map(this::adapt)
.collect(toList()));
return view;
}
private HashMap adapt(DocumentationItem serviceDoc) {
HashMap view = new HashMap<>();
view.put("id", serviceDoc.id());
view.put("name", serviceDoc.name());
view.put("description", serviceDoc.description().description().orElse(""));
return view;
}
private HashMap adaptDomainProcess(DocumentationItem domainProcessDoc, Domain domain) {
HashMap view = new HashMap<>();
view.put("id", domainProcessDoc.id());
view.put("name", domainProcessDoc.name());
view.put("description", domainProcessDoc.description().description().orElse(""));
var domainProcessSteps = DomainProcessStepsFactory.buildDomainProcessGraphNodes(domainProcessDoc,
domain);
view.put("steps", domainProcessSteps.orderedSteps().stream()
.filter(step -> !step.componentDoc().description().trivial())
.filter(step -> !step.external())
.map(this::adapt)
.collect(toList()));
return view;
}
private HashMap adapt(DomainProcessGraphNode step) {
HashMap view = new HashMap<>();
view.put("name", step.componentDoc().name());
view.put("description", step.componentDoc().description().description().orElse(""));
return view;
}
private HashMap adapt(UbiquitousLanguageEntry entry) {
HashMap view = new HashMap<>();
view.put("name", entry.qualifiedName());
view.put("type", entry.getType());
view.put("description", entry.componentDoc().shortDescriptionOrDefault());
return view;
}
private void copyCss()
throws IOException {
IOUtils.copy(getClass().getResourceAsStream("/style.css"),
new FileOutputStream(new File(outputDirectoryPath, "style.css")));
}
private UbiquitousLanguageFactory ubitquitousLanguageFactory = new UbiquitousLanguageFactory();
public static class Builder {
public HtmlWriter build() {
requireNonNull(writer.outputDirectoryPath);
return writer;
}
private HtmlWriter writer = new HtmlWriter();
public Builder outputDirectoryPath(String outputDirectoryPath) {
writer.outputDirectoryPath = outputDirectoryPath;
return this;
}
public Builder includeGenerationDate(boolean includeGenerationDate) {
writer.includeGenerationDate = includeGenerationDate;
return this;
}
}
private HtmlWriter() {
}
}