org.hl7.fhir.r5.comparison.ComparisonRenderer Maven / Gradle / Ivy
package org.hl7.fhir.r5.comparison;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.comparison.CapabilityStatementComparer.CapabilityStatementComparison;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.PlaceHolderComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison;
import org.hl7.fhir.r5.comparison.StructureDefinitionComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
import org.hl7.fhir.r5.fhirpath.TypeDetails;
import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.liquid.LiquidEngine;
import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.Tuple;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.FileUtilities;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
@MarkedToMoveToAdjunctPackage
public class ComparisonRenderer implements IEvaluationContext {
private IWorkerContext contextLeft;
private IWorkerContext contextRight;
private ComparisonSession session;
private Map templates = new HashMap<>();
private String folder;
private String preamble;
public ComparisonRenderer(IWorkerContext contextLeft, IWorkerContext contextRight, String folder, ComparisonSession session) {
super();
this.contextLeft = contextLeft;
this.contextRight = contextRight;
this.folder = folder;
this.session = session;
}
public String getPreamble() {
return preamble;
}
public void setPreamble(String preamble) {
this.preamble = preamble;
}
public Map getTemplates() {
return templates;
}
public File render(String leftName, String rightName) throws IOException {
dumpBinaries();
StringBuilder b = new StringBuilder();
if (preamble != null) {
b.append(preamble);
}
b.append("\r\n");
b.append(" \r\n");
b.append(" "+Utilities.escapeXml(leftName)+" \r\n");
b.append(" "+Utilities.escapeXml(rightName)+" \r\n");
b.append(" Difference \r\n");
b.append(" Union \r\n");
b.append(" Intersection \r\n");
b.append(" Notes \r\n");
b.append(" \r\n");
List list = sorted(session.getCompares().keySet());
processList(list, b, "CodeSystem");
processList(list, b, "ValueSet");
processList(list, b, "StructureDefinition");
processList(list, b, "CapabilityStatement");
b.append("
\r\n");
Map vars = new HashMap<>();
vars.put("title", new StringType(session.getTitle()));
vars.put("list", new StringType(b.toString()));
String template = templates.get("Index");
String cnt = processTemplate(template, "CodeSystem", vars);
FileUtilities.stringToFile(cnt, file("index.html"));
return ManagedFileAccess.file(file("index.html"));
}
private void processList(List list, StringBuilder b, String name) throws IOException {
// TODO Auto-generated method stub
boolean first = true;
for (String id : list) {
ResourceComparison comp = session.getCompares().get(id);
if (comp.fhirType().equals(name)) {
if (first) {
first = false;
b.append(""+Utilities.pluralize(name, 2)+" \r\n");
}
try {
renderComparison(id, comp);
} catch (Exception e) {
System.out.println("Exception rendering "+id+": "+e.getMessage());
e.printStackTrace();
}
b.append(comp.toTable());
//""+Utilities.escapeXml(comp.summary())+" \r\n"
}
}
}
private List sorted(Set keySet) {
List list = new ArrayList<>();
list.addAll(keySet);
Collections.sort(list);
return list;
}
private void dumpBinaries() throws IOException {
if (contextLeft != null && contextLeft.getBinaryKeysAsSet() != null) {
for (String k : contextLeft.getBinaryKeysAsSet()) {
FileUtilities.bytesToFile(contextLeft.getBinaryForKey(k), Utilities.path(folder, k));
}
}
if (contextRight != null && contextRight.getBinaryKeysAsSet() != null) {
for (String k : contextRight.getBinaryKeysAsSet()) {
FileUtilities.bytesToFile(contextRight.getBinaryForKey(k), Utilities.path(folder, k));
}
}
}
private void renderComparison(String id, ResourceComparison comp) throws IOException, FHIRFormatError, DefinitionException, FHIRException, EOperationOutcome {
if (comp instanceof ProfileComparison) {
renderProfile(id, (ProfileComparison) comp);
} else if (comp instanceof ValueSetComparison) {
renderValueSet(id, (ValueSetComparison) comp);
} else if (comp instanceof CodeSystemComparison) {
renderCodeSystem(id, (CodeSystemComparison) comp);
} else if (comp instanceof CapabilityStatementComparison) {
renderCapabilityStatement(id, (CapabilityStatementComparison) comp);
} else if (comp instanceof PlaceHolderComparison) {
renderPlaceHolder(id, (PlaceHolderComparison) comp);
}
}
private void renderPlaceHolder(String id, PlaceHolderComparison comp) throws IOException {
String cnt = "";
if (comp.getE() != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
comp.getE().printStackTrace(pw);
cnt = sw.toString();
}
cnt = ""+cnt+"
\r\n";
FileUtilities.stringToFile(cnt, file(comp.getId()+".html"));
}
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException, FHIRFormatError, DefinitionException, FHIRException, EOperationOutcome {
String template = templates.get("CodeSystem");
Map vars = new HashMap<>();
CodeSystemComparer cs = new CodeSystemComparer(session);
vars.put("left", new StringType(comp.getLeft().present()));
vars.put("right", new StringType(comp.getRight().present()));
vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("summary", new StringType(comp.summary()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
vars.put("concepts", new StringType(new XhtmlComposer(true).compose(cs.renderConcepts(comp, "", ""))));
String cnt = processTemplate(template, "CodeSystem", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
String union = new XhtmlComposer(true).compose(cs.renderUnion(comp, "", folder, "http://hl7.org/fhir"));
String intersection = new XhtmlComposer(true).compose(cs.renderIntersection(comp, "", folder, "http://hl7.org/fhir"));
vars.put("union", new StringType(union));
vars.put("intersection", new StringType(intersection));
template = templates.get("CodeSystem-Union");
cnt = processTemplate(template, "CodeSystem-Union", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-union.html"));
template = templates.get("CodeSystem-Intersection");
cnt = processTemplate(template, "CodeSystem-Intersection", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-intersection.html"));
}
private String file(String name) throws IOException {
return Utilities.path(folder, name);
}
private void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException, EOperationOutcome {
String template = templates.get("ValueSet");
Map vars = new HashMap<>();
ValueSetComparer cs = new ValueSetComparer(session);
vars.put("left", new StringType(comp.getLeft().present()));
vars.put("right", new StringType(comp.getRight().present()));
vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("summary", new StringType(comp.summary()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
vars.put("compose", new StringType(new XhtmlComposer(true).compose(cs.renderCompose(comp, "", ""))));
vars.put("expansion", new StringType(new XhtmlComposer(true).compose(cs.renderExpansion(comp, "", ""))));
String cnt = processTemplate(template, "ValueSet", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
String union = new XhtmlComposer(true).compose(cs.renderUnion(comp, "", folder, "http://hl7.org/fhir"));
String intersection = new XhtmlComposer(true).compose(cs.renderIntersection(comp, "", folder, "http://hl7.org/fhir"));
vars.put("union", new StringType(union));
vars.put("intersection", new StringType(intersection));
template = templates.get("ValueSet-Union");
cnt = processTemplate(template, "ValueSet-Union", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-union.html"));
template = templates.get("ValueSet-Intersection");
cnt = processTemplate(template, "ValueSet-Intersection", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-intersection.html"));
}
private void renderProfile(String id, ProfileComparison comp) throws IOException {
String template = templates.get("Profile");
Map vars = new HashMap<>();
StructureDefinitionComparer cs = new StructureDefinitionComparer(session, new ProfileUtilities(session.getContextLeft(), null, session.getPkpLeft()),
new ProfileUtilities(session.getContextRight(), null, session.getPkpRight()));
vars.put("left", new StringType(comp.getLeft().present()));
vars.put("right", new StringType(comp.getRight().present()));
vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
vars.put("structure", new StringType(new XhtmlComposer(true).compose(cs.renderStructure(comp, "", "", "http://hl7.org/fhir"))));
String union = new XhtmlComposer(true).compose(cs.renderUnion(comp, "", folder, "http://hl7.org/fhir"));
String intersection = new XhtmlComposer(true).compose(cs.renderIntersection(comp, "", folder, "http://hl7.org/fhir"));
vars.put("union", new StringType(union));
vars.put("intersection", new StringType(intersection));
String cnt = processTemplate(template, "Profile", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+".html"));
template = templates.get("Profile-Union");
cnt = processTemplate(template, "Profile-Union", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-union.html"));
template = templates.get("Profile-Intersection");
cnt = processTemplate(template, "Profile-Intersection", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+"-intersection.html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
}
private void renderCapabilityStatement(String id, CapabilityStatementComparison comp) throws IOException {
String template = templates.get("CapabilityStatement");
Map vars = new HashMap<>();
CapabilityStatementComparer cs = new CapabilityStatementComparer(session);
vars.put("left", new StringType(comp.getLeft().present()));
vars.put("right", new StringType(comp.getRight().present()));
vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
vars.put("statement", new StringType(new XhtmlComposer(true).compose(cs.renderStatements(comp, "", ""))));
String cnt = processTemplate(template, "CapabilityStatement", vars);
FileUtilities.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(folder, comp.getId() + "-intersection.json")), comp.getIntersection());
}
private String processTemplate(String template, String name, Map vars) {
LiquidEngine engine = new LiquidEngine(contextRight, this);
LiquidDocument doc = engine.parse(template, name+".template");
return engine.evaluate(doc, Tuple.fromMap(FhirPublication.R5, vars), vars);
}
@Override
public List resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException {
@SuppressWarnings("unchecked")
Map vars = (Map) appContext;
List res = new ArrayList<>();
if (vars.containsKey(name)) {
res.add(vars.get(name));
}
return res;
}
@Override
public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name, boolean explicitConstant) throws PathEngineException {
@SuppressWarnings("unchecked")
Map vars = (Map) appContext;
Base b = vars.get(name);
return new TypeDetails(CollectionStatus.SINGLETON, b == null ? "Base" : b.fhirType());
}
@Override
public boolean log(String argument, List focus) {
return false;
}
@Override
public FunctionDetails resolveFunction(FHIRPathEngine engine, String functionName) {
return null;
}
@Override
public TypeDetails checkFunction(FHIRPathEngine engine, Object appContext, String functionName, TypeDetails focus, List parameters) throws PathEngineException {
return null;
}
@Override
public List executeFunction(FHIRPathEngine engine, Object appContext, List focus, String functionName, List> parameters) {
return null;
}
@Override
public Base resolveReference(FHIRPathEngine engine, Object appContext, String url, Base refContext) throws FHIRException {
return null;
}
@Override
public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base item, String url) throws FHIRException {
return false;
}
@Override
public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) {
return null;
}
@Override
public boolean paramIsType(String name, int index) {
return false;
}
public void loadTemplates(IWorkerContext context) {
getTemplates().put("CapabilityStatement", new String(context.getBinaryForKey("template-comparison-CapabilityStatement.html")));
getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html")));
getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html")));
getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html")));
getTemplates().put("Index", new String(context.getBinaryForKey("template-comparison-index.html")));
getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html")));
getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html")));
getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html")));
getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html")));
getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html")));
getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html")));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy