ModelToAstMapper.java
package com.taxonomy.dsl.mapper;
import com.taxonomy.dsl.ast.*;
import com.taxonomy.dsl.model.*;
import java.util.*;
/**
* Maps canonical architecture model objects back to {@link BlockAst} nodes
* for serialization to DSL text.
*/
public class ModelToAstMapper {
/**
* Map a complete canonical model to a document AST including meta header.
*/
public DocumentAst toDocument(CanonicalArchitectureModel model, String namespace) {
MetaAst meta = new MetaAst(MetaAst.LANGUAGE_ID, MetaAst.CURRENT_VERSION, namespace, null);
List<BlockAst> blocks = new ArrayList<>();
for (ArchitectureElement el : model.getElements()) {
blocks.add(elementToBlock(el));
}
for (ArchitectureRelation rel : model.getRelations()) {
blocks.add(relationToBlock(rel));
}
for (ArchitectureRequirement req : model.getRequirements()) {
blocks.add(requirementToBlock(req));
}
for (RequirementMapping mapping : model.getMappings()) {
blocks.add(mappingToBlock(mapping));
}
for (ArchitectureView view : model.getViews()) {
blocks.add(viewToBlock(view));
}
for (ArchitectureEvidence ev : model.getEvidence()) {
blocks.add(evidenceToBlock(ev));
}
for (ArchitectureSource src : model.getSources()) {
blocks.add(sourceToBlock(src));
}
for (ArchitectureSourceVersion sv : model.getSourceVersions()) {
blocks.add(sourceVersionToBlock(sv));
}
for (ArchitectureSourceFragment sf : model.getSourceFragments()) {
blocks.add(sourceFragmentToBlock(sf));
}
for (ArchitectureRequirementSourceLink rsl : model.getRequirementSourceLinks()) {
blocks.add(requirementSourceLinkToBlock(rsl));
}
return new DocumentAst(meta, blocks);
}
private BlockAst elementToBlock(ArchitectureElement el) {
List<String> headerTokens = new ArrayList<>();
if (el.getId() != null) headerTokens.add(el.getId());
if (el.getType() != null) {
headerTokens.add("type");
headerTokens.add(el.getType());
}
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "title", el.getTitle());
addProperty(props, "description", el.getDescription());
addProperty(props, "taxonomy", el.getTaxonomy());
addExtensions(props, el.getExtensions());
return new BlockAst("element", headerTokens, props, List.of(), el.getExtensions(), null);
}
private BlockAst relationToBlock(ArchitectureRelation rel) {
List<String> headerTokens = new ArrayList<>();
if (rel.getSourceId() != null) headerTokens.add(rel.getSourceId());
if (rel.getRelationType() != null) headerTokens.add(rel.getRelationType());
if (rel.getTargetId() != null) headerTokens.add(rel.getTargetId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "status", rel.getStatus());
if (rel.getConfidence() != null) {
addProperty(props, "confidence", String.valueOf(rel.getConfidence()));
}
addProperty(props, "provenance", rel.getProvenance());
addExtensions(props, rel.getExtensions());
return new BlockAst("relation", headerTokens, props, List.of(), rel.getExtensions(), null);
}
private BlockAst requirementToBlock(ArchitectureRequirement req) {
List<String> headerTokens = new ArrayList<>();
if (req.getId() != null) headerTokens.add(req.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "title", req.getTitle());
addProperty(props, "text", req.getText());
addExtensions(props, req.getExtensions());
return new BlockAst("requirement", headerTokens, props, List.of(), req.getExtensions(), null);
}
private BlockAst mappingToBlock(RequirementMapping mapping) {
List<String> headerTokens = new ArrayList<>();
if (mapping.getRequirementId() != null) headerTokens.add(mapping.getRequirementId());
headerTokens.add("->");
if (mapping.getElementId() != null) headerTokens.add(mapping.getElementId());
List<PropertyAst> props = new ArrayList<>();
if (mapping.getScore() != null) {
addProperty(props, "score", String.valueOf(mapping.getScore()));
}
addProperty(props, "source", mapping.getSource());
addExtensions(props, mapping.getExtensions());
return new BlockAst("mapping", headerTokens, props, List.of(), mapping.getExtensions(), null);
}
private BlockAst viewToBlock(ArchitectureView view) {
List<String> headerTokens = new ArrayList<>();
if (view.getId() != null) headerTokens.add(view.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "title", view.getTitle());
for (String inc : view.getIncludes()) {
addProperty(props, "include", inc);
}
addProperty(props, "layout", view.getLayout());
addExtensions(props, view.getExtensions());
return new BlockAst("view", headerTokens, props, List.of(), view.getExtensions(), null);
}
private BlockAst evidenceToBlock(ArchitectureEvidence ev) {
List<String> headerTokens = new ArrayList<>();
if (ev.getId() != null) headerTokens.add(ev.getId());
List<PropertyAst> props = new ArrayList<>();
// Serialize for-relation as a property: "SOURCE TYPE TARGET"
if (ev.getForRelationSource() != null) {
StringBuilder forRel = new StringBuilder(ev.getForRelationSource());
if (ev.getForRelationType() != null) forRel.append(' ').append(ev.getForRelationType());
if (ev.getForRelationTarget() != null) forRel.append(' ').append(ev.getForRelationTarget());
addProperty(props, "for-relation", forRel.toString());
}
addProperty(props, "type", ev.getEvidenceType());
addProperty(props, "model", ev.getModel());
if (ev.getConfidence() != null) {
addProperty(props, "confidence", String.valueOf(ev.getConfidence()));
}
addProperty(props, "summary", ev.getSummary());
addExtensions(props, ev.getExtensions());
return new BlockAst("evidence", headerTokens, props, List.of(), ev.getExtensions(), null);
}
private BlockAst sourceToBlock(ArchitectureSource src) {
List<String> headerTokens = new ArrayList<>();
if (src.getId() != null) headerTokens.add(src.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "type", src.getSourceType());
addProperty(props, "title", src.getTitle());
addProperty(props, "canonicalIdentifier", src.getCanonicalIdentifier());
addProperty(props, "canonicalUrl", src.getCanonicalUrl());
addProperty(props, "originSystem", src.getOriginSystem());
addProperty(props, "language", src.getLanguage());
addExtensions(props, src.getExtensions());
return new BlockAst("source", headerTokens, props, List.of(), src.getExtensions(), null);
}
private BlockAst sourceVersionToBlock(ArchitectureSourceVersion sv) {
List<String> headerTokens = new ArrayList<>();
if (sv.getId() != null) headerTokens.add(sv.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "source", sv.getSourceId());
addProperty(props, "versionLabel", sv.getVersionLabel());
addProperty(props, "retrievedAt", sv.getRetrievedAt());
addProperty(props, "effectiveDate", sv.getEffectiveDate());
addProperty(props, "mimeType", sv.getMimeType());
addProperty(props, "contentHash", sv.getContentHash());
addExtensions(props, sv.getExtensions());
return new BlockAst("sourceVersion", headerTokens, props, List.of(), sv.getExtensions(), null);
}
private BlockAst sourceFragmentToBlock(ArchitectureSourceFragment sf) {
List<String> headerTokens = new ArrayList<>();
if (sf.getId() != null) headerTokens.add(sf.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "sourceVersion", sf.getSourceVersionId());
addProperty(props, "sectionPath", sf.getSectionPath());
addProperty(props, "paragraphRef", sf.getParagraphRef());
if (sf.getPageFrom() != null) {
addProperty(props, "pageFrom", String.valueOf(sf.getPageFrom()));
}
if (sf.getPageTo() != null) {
addProperty(props, "pageTo", String.valueOf(sf.getPageTo()));
}
addProperty(props, "text", sf.getText());
addProperty(props, "fragmentHash", sf.getFragmentHash());
addExtensions(props, sf.getExtensions());
return new BlockAst("sourceFragment", headerTokens, props, List.of(), sf.getExtensions(), null);
}
private BlockAst requirementSourceLinkToBlock(ArchitectureRequirementSourceLink rsl) {
List<String> headerTokens = new ArrayList<>();
if (rsl.getId() != null) headerTokens.add(rsl.getId());
List<PropertyAst> props = new ArrayList<>();
addProperty(props, "requirement", rsl.getRequirementId());
addProperty(props, "source", rsl.getSourceId());
addProperty(props, "sourceVersion", rsl.getSourceVersionId());
addProperty(props, "sourceFragment", rsl.getSourceFragmentId());
addProperty(props, "linkType", rsl.getLinkType());
if (rsl.getConfidence() != null) {
addProperty(props, "confidence", String.valueOf(rsl.getConfidence()));
}
addProperty(props, "note", rsl.getNote());
addExtensions(props, rsl.getExtensions());
return new BlockAst("requirementSourceLink", headerTokens, props, List.of(), rsl.getExtensions(), null);
}
private void addProperty(List<PropertyAst> props, String key, String value) {
if (value != null) {
props.add(new PropertyAst(key, value, null));
}
}
private void addExtensions(List<PropertyAst> props, Map<String, String> extensions) {
if (extensions != null) {
for (Map.Entry<String, String> entry : extensions.entrySet()) {
props.add(new PropertyAst(entry.getKey(), entry.getValue(), null));
}
}
}
}