Merge branch 'release' into merge_branch

This commit is contained in:
Mark Iantorno 2020-06-12 19:34:50 -04:00 committed by GitHub
commit f5455bb9e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 451 additions and 456 deletions

View File

@ -1,7 +1,8 @@
* Override extension methods in BackboneElement to look in modifierExtensions as well as extensions * Override extension methods in BackboneElement to look in modifierExtensions as well as extensions
* First draft of Profile Comparison tools (org.hl7.fhir.r5.comparison) * First draft of Profile Comparison tools (org.hl7.fhir.r5.comparison)
* Improved error messages when snapshot generation fails when slicing something that doesn't repeat * Improved error messages when snapshot generation fails when slicing something that doesn't repeat
* Improvements for CDA round-tripping (XML esacping issues, xsi:type related issues, namespacing issues) * Improvements for CDA round-tripping (XML esacping issues, xsi:type related issues, namespacing issues)
* Fix bug rendering DiagnosticReports with multiple categories * Fix bug rendering DiagnosticReports with multiple categories
* adjust check on Attachment to only be an warning (when no meaningful content exists) * adjust check on Attachment to only be an warning (when no meaningful content exists)
* add security check mode to Validator * add security check mode to Validator

View File

@ -1,212 +1,213 @@
package org.hl7.fhir.r5.comparison; package org.hl7.fhir.r5.comparison;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison; import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison; import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus; import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.model.Tuple; import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.TypeDetails; import org.hl7.fhir.r5.model.Tuple;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.utils.LiquidEngine; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.r5.utils.LiquidEngine;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
public class ComparisonRenderer implements IEvaluationContext { import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
private IWorkerContext context; public class ComparisonRenderer implements IEvaluationContext {
private ComparisonSession session;
private Map<String, String> templates = new HashMap<>(); private IWorkerContext context;
private String folder; private ComparisonSession session;
private Map<String, String> templates = new HashMap<>();
public ComparisonRenderer(IWorkerContext context, String folder, ComparisonSession session) { private String folder;
super();
this.context = context; public ComparisonRenderer(IWorkerContext context, String folder, ComparisonSession session) {
this.folder = folder; super();
this.session = session; this.context = context;
} this.folder = folder;
this.session = session;
public Map<String, String> getTemplates() { }
return templates;
} public Map<String, String> getTemplates() {
return templates;
public void render() throws IOException { }
dumpBinaries();
StringBuilder b = new StringBuilder(); public void render() throws IOException {
dumpBinaries();
for (String id : sorted(session.getCompares().keySet())) { StringBuilder b = new StringBuilder();
ResourceComparison comp = session.getCompares().get(id);
renderComparison(id, comp); for (String id : sorted(session.getCompares().keySet())) {
b.append("<li><a href=\""+comp.getId()+".html\">"+Utilities.escapeXml(comp.summary())+"</a></li>\r\n"); ResourceComparison comp = session.getCompares().get(id);
} renderComparison(id, comp);
Map<String, Base> vars = new HashMap<>(); b.append("<li><a href=\""+comp.getId()+".html\">"+Utilities.escapeXml(comp.summary())+"</a></li>\r\n");
CodeSystemComparer cs = new CodeSystemComparer(session); }
vars.put("title", new StringType(session.getTitle())); Map<String, Base> vars = new HashMap<>();
vars.put("list", new StringType(b.toString())); CodeSystemComparer cs = new CodeSystemComparer(session);
String template = templates.get("Index"); vars.put("title", new StringType(session.getTitle()));
String cnt = processTemplate(template, "CodeSystem", vars); vars.put("list", new StringType(b.toString()));
TextFile.stringToFile(cnt, file("index.html")); String template = templates.get("Index");
} String cnt = processTemplate(template, "CodeSystem", vars);
TextFile.stringToFile(cnt, file("index.html"));
private List<String> sorted(Set<String> keySet) { }
List<String> list = new ArrayList<>();
list.addAll(keySet); private List<String> sorted(Set<String> keySet) {
Collections.sort(list); List<String> list = new ArrayList<>();
return list; list.addAll(keySet);
} Collections.sort(list);
return list;
private void dumpBinaries() throws IOException { }
for (String k : context.getBinaries().keySet()) {
TextFile.bytesToFile(context.getBinaries().get(k), Utilities.path(folder, k)); private void dumpBinaries() throws IOException {
} for (String k : context.getBinaries().keySet()) {
TextFile.bytesToFile(context.getBinaries().get(k), Utilities.path(folder, k));
} }
}
private void renderComparison(String id, ResourceComparison comp) throws IOException {
if (comp instanceof ProfileComparison) { private void renderComparison(String id, ResourceComparison comp) throws IOException {
renderProfile(id, (ProfileComparison) comp); if (comp instanceof ProfileComparison) {
} else if (comp instanceof ValueSetComparison) { renderProfile(id, (ProfileComparison) comp);
renderValueSet(id, (ValueSetComparison) comp); } else if (comp instanceof ValueSetComparison) {
} else if (comp instanceof CodeSystemComparison) { renderValueSet(id, (ValueSetComparison) comp);
renderCodeSystem(id, (CodeSystemComparison) comp); } else if (comp instanceof CodeSystemComparison) {
} renderCodeSystem(id, (CodeSystemComparison) comp);
} }
}
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException {
String template = templates.get("CodeSystem"); private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException {
Map<String, Base> vars = new HashMap<>(); String template = templates.get("CodeSystem");
CodeSystemComparer cs = new CodeSystemComparer(session); Map<String, Base> vars = new HashMap<>();
vars.put("left", new StringType(comp.getLeft().present())); CodeSystemComparer cs = new CodeSystemComparer(session);
vars.put("right", new StringType(comp.getRight().present())); vars.put("left", new StringType(comp.getLeft().present()));
vars.put("leftId", new StringType(comp.getLeft().getId())); vars.put("right", new StringType(comp.getRight().present()));
vars.put("rightId", new StringType(comp.getRight().getId())); vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl())); vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl())); vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp)))); vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", "")))); vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("concepts", new StringType(new XhtmlComposer(true).compose(cs.renderConcepts(comp, "", "")))); vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
String cnt = processTemplate(template, "CodeSystem", vars); vars.put("concepts", new StringType(new XhtmlComposer(true).compose(cs.renderConcepts(comp, "", ""))));
TextFile.stringToFile(cnt, file(comp.getId()+".html")); String cnt = processTemplate(template, "CodeSystem", vars);
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion()); TextFile.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion());
} new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection());
}
private String file(String name) throws IOException {
return Utilities.path(folder, name); private String file(String name) throws IOException {
} return Utilities.path(folder, name);
}
private void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException {
String template = templates.get("ValueSet"); private void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException {
Map<String, Base> vars = new HashMap<>(); String template = templates.get("ValueSet");
ValueSetComparer cs = new ValueSetComparer(session); Map<String, Base> vars = new HashMap<>();
vars.put("left", new StringType(comp.getLeft().present())); ValueSetComparer cs = new ValueSetComparer(session);
vars.put("right", new StringType(comp.getRight().present())); vars.put("left", new StringType(comp.getLeft().present()));
vars.put("leftId", new StringType(comp.getLeft().getId())); vars.put("right", new StringType(comp.getRight().present()));
vars.put("rightId", new StringType(comp.getRight().getId())); vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl())); vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl())); vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp)))); vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", "")))); vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("compose", new StringType(new XhtmlComposer(true).compose(cs.renderCompose(comp, "", "")))); vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
vars.put("expansion", new StringType(new XhtmlComposer(true).compose(cs.renderExpansion(comp, "", "")))); vars.put("compose", new StringType(new XhtmlComposer(true).compose(cs.renderCompose(comp, "", ""))));
String cnt = processTemplate(template, "ValueSet", vars); vars.put("expansion", new StringType(new XhtmlComposer(true).compose(cs.renderExpansion(comp, "", ""))));
TextFile.stringToFile(cnt, file(comp.getId()+".html")); String cnt = processTemplate(template, "ValueSet", vars);
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion()); TextFile.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion());
} new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection());
}
private void renderProfile(String id, ProfileComparison comp) throws IOException {
String template = templates.get("Profile"); private void renderProfile(String id, ProfileComparison comp) throws IOException {
Map<String, Base> vars = new HashMap<>(); String template = templates.get("Profile");
ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContext(), null, null)); Map<String, Base> vars = new HashMap<>();
vars.put("left", new StringType(comp.getLeft().present())); ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContext(), null, null));
vars.put("right", new StringType(comp.getRight().present())); vars.put("left", new StringType(comp.getLeft().present()));
vars.put("leftId", new StringType(comp.getLeft().getId())); vars.put("right", new StringType(comp.getRight().present()));
vars.put("rightId", new StringType(comp.getRight().getId())); vars.put("leftId", new StringType(comp.getLeft().getId()));
vars.put("leftUrl", new StringType(comp.getLeft().getUrl())); vars.put("rightId", new StringType(comp.getRight().getId()));
vars.put("rightUrl", new StringType(comp.getRight().getUrl())); vars.put("leftUrl", new StringType(comp.getLeft().getUrl()));
vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp)))); vars.put("rightUrl", new StringType(comp.getRight().getUrl()));
vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", "")))); vars.put("errors", new StringType(new XhtmlComposer(true).compose(cs.renderErrors(comp))));
vars.put("structure", new StringType(new XhtmlComposer(true).compose(cs.renderStructure(comp, "", "", "http://hl7.org/fhir")))); vars.put("metadata", new StringType(new XhtmlComposer(true).compose(cs.renderMetadata(comp, "", ""))));
String cnt = processTemplate(template, "CodeSystem", vars); vars.put("structure", new StringType(new XhtmlComposer(true).compose(cs.renderStructure(comp, "", "", "http://hl7.org/fhir"))));
TextFile.stringToFile(cnt, file(comp.getId()+".html")); String cnt = processTemplate(template, "CodeSystem", vars);
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion()); TextFile.stringToFile(cnt, file(comp.getId()+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-union.json")), comp.getUnion());
} new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", comp.getId() + "-intersection.json")), comp.getIntersection());
}
private String processTemplate(String template, String name, Map<String, Base> vars) {
LiquidEngine engine = new LiquidEngine(context, this); private String processTemplate(String template, String name, Map<String, Base> vars) {
LiquidDocument doc = engine.parse(template, name+".template"); LiquidEngine engine = new LiquidEngine(context, this);
return engine.evaluate(doc, Tuple.fromMap(vars), vars); LiquidDocument doc = engine.parse(template, name+".template");
} return engine.evaluate(doc, Tuple.fromMap(vars), vars);
}
@Override
public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException { @Override
@SuppressWarnings("unchecked") public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException {
Map<String, Base> vars = (Map<String, Base>) appContext; @SuppressWarnings("unchecked")
return vars.get(name); Map<String, Base> vars = (Map<String, Base>) appContext;
} return vars.get(name);
}
@Override
public TypeDetails resolveConstantType(Object appContext, String name) throws PathEngineException { @Override
@SuppressWarnings("unchecked") public TypeDetails resolveConstantType(Object appContext, String name) throws PathEngineException {
Map<String, Base> vars = (Map<String, Base>) appContext; @SuppressWarnings("unchecked")
Base b = vars.get(name); Map<String, Base> vars = (Map<String, Base>) appContext;
return new TypeDetails(CollectionStatus.SINGLETON, b == null ? "Base" : b.fhirType()); Base b = vars.get(name);
} return new TypeDetails(CollectionStatus.SINGLETON, b == null ? "Base" : b.fhirType());
}
@Override
public boolean log(String argument, List<Base> focus) { @Override
return false; public boolean log(String argument, List<Base> focus) {
} return false;
}
@Override
public FunctionDetails resolveFunction(String functionName) { @Override
return null; public FunctionDetails resolveFunction(String functionName) {
} return null;
}
@Override
public TypeDetails checkFunction(Object appContext, String functionName, List<TypeDetails> parameters) throws PathEngineException { @Override
return null; public TypeDetails checkFunction(Object appContext, String functionName, List<TypeDetails> parameters) throws PathEngineException {
} return null;
}
@Override
public List<Base> executeFunction(Object appContext, String functionName, List<List<Base>> parameters) { @Override
return null; public List<Base> executeFunction(Object appContext, String functionName, List<List<Base>> parameters) {
} return null;
}
@Override
public Base resolveReference(Object appContext, String url, Base refContext) throws FHIRException { @Override
return null; public Base resolveReference(Object appContext, String url, Base refContext) throws FHIRException {
} return null;
}
@Override
public boolean conformsToProfile(Object appContext, Base item, String url) throws FHIRException { @Override
return false; public boolean conformsToProfile(Object appContext, Base item, String url) throws FHIRException {
} return false;
}
@Override
public ValueSet resolveValueSet(Object appContext, String url) { @Override
return null; public ValueSet resolveValueSet(Object appContext, String url) {
} return null;
}
}
}

View File

@ -1,122 +1,114 @@
package org.hl7.fhir.r5.comparison; package org.hl7.fhir.r5.comparison;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison; import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison; import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
public class ComparisonSession { public class ComparisonSession {
private Map<String, ResourceComparison> compares = new HashMap<>(); private Map<String, ResourceComparison> compares = new HashMap<>();
private IWorkerContext context; private IWorkerContext context;
private String sessiondId; private String sessiondId;
private int count; private int count;
private boolean debug; private boolean debug;
private String title; private String title;
public ComparisonSession(IWorkerContext context, String title) { public ComparisonSession(IWorkerContext context, String title) {
super(); super();
this.context = context; this.context = context;
this.sessiondId = UUID.randomUUID().toString().toLowerCase(); this.sessiondId = UUID.randomUUID().toString().toLowerCase();
this.title = title; this.title = title;
// debug = true; // debug = true;
} }
public IWorkerContext getContext() { public IWorkerContext getContext() {
return context; return context;
} }
public String getTitle() {
return title;
public String getTitle() { }
return title;
} public ResourceComparison compare(String left, String right) throws DefinitionException, FHIRFormatError, IOException {
CanonicalResource l = (CanonicalResource) context.fetchResource(Resource.class, left);
public ResourceComparison compare(String left, String right) throws DefinitionException, FHIRFormatError, IOException { if (l == null) {
CanonicalResource l = (CanonicalResource) context.fetchResource(Resource.class, left); throw new DefinitionException("Unable to resolve "+left);
if (l == null) { }
throw new DefinitionException("Unable to resolve "+left); CanonicalResource r = (CanonicalResource) context.fetchResource(Resource.class, right);
} if (r == null) {
CanonicalResource r = (CanonicalResource) context.fetchResource(Resource.class, right); throw new DefinitionException("Unable to resolve "+right);
if (r == null) { }
throw new DefinitionException("Unable to resolve "+right); return compare(l, r);
} }
return compare(l, r);
} public ResourceComparison compare(CanonicalResource left, CanonicalResource right) throws DefinitionException, FHIRFormatError, IOException {
String key = key(left.getUrl(), left.getVersion(), right.getUrl(), right.getVersion());
public ResourceComparison compare(CanonicalResource left, CanonicalResource right) throws DefinitionException, FHIRFormatError, IOException { if (compares.containsKey(key)) {
String key = key(left.getUrl(), left.getVersion(), right.getUrl(), right.getVersion()); // if null then the comparison is in progress.
if (compares.containsKey(key)) { // this can happen when profiles refer to each other
// if null then the comparison is in progress. return compares.get(key);
// this can happen when profiles refer to each other }
return compares.get(key); compares.put(key, null);
} if (left instanceof CodeSystem && right instanceof CodeSystem) {
compares.put(key, null); CodeSystemComparer cs = new CodeSystemComparer(this);
if (left instanceof CodeSystem && right instanceof CodeSystem) { CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right);
CodeSystemComparer cs = new CodeSystemComparer(this); compares.put(key, csc);
CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right); return csc;
compares.put(key, csc); } else if (left instanceof ValueSet && right instanceof ValueSet) {
return csc; ValueSetComparer cs = new ValueSetComparer(this);
} else if (left instanceof ValueSet && right instanceof ValueSet) { ValueSetComparison csc = cs.compare((ValueSet) left, (ValueSet) right);
ValueSetComparer cs = new ValueSetComparer(this); compares.put(key, csc);
ValueSetComparison csc = cs.compare((ValueSet) left, (ValueSet) right); return csc;
compares.put(key, csc); } else if (left instanceof StructureDefinition && right instanceof StructureDefinition) {
return csc; ProfileComparer cs = new ProfileComparer(this, new ProfileUtilities(context, null, null));
} else if (left instanceof StructureDefinition && right instanceof StructureDefinition) { ProfileComparison csc = cs.compare((StructureDefinition) left, (StructureDefinition) right);
ProfileComparer cs = new ProfileComparer(this, new ProfileUtilities(context, null, null)); compares.put(key, csc);
ProfileComparison csc = cs.compare((StructureDefinition) left, (StructureDefinition) right); return csc;
compares.put(key, csc); } else {
return csc; throw new FHIRException("Unable to compare ");
} else { }
throw new FHIRException("Unable to compare "); }
}
} private String key(String urlL, String verL, String urlR, String verR) {
return urlL+"|"+verL+"||"+urlR+"|"+verR;
private String key(String urlL, String verL, String urlR, String verR) { }
return urlL+"|"+verL+"||"+urlR+"|"+verR;
} public void identify(CanonicalResource res) {
count++;
res.setId(sessiondId+"-"+count);
public void identify(CanonicalResource res) { res.setUrl("http://hl7.org/fhir/comparison/"+res.fhirType()+"/"+res.getId());
count++; }
res.setId(sessiondId+"-"+count);
res.setUrl("http://hl7.org/fhir/comparison/"+res.fhirType()+"/"+res.getId()); public void identify(ResourceComparison res) {
} count++;
}
public void identify(ResourceComparison res) {
count++; public boolean isDebug() {
} return debug;
}
public boolean isDebug() {
return debug; public void setDebug(boolean debug) {
} this.debug = debug;
}
public void setDebug(boolean debug) {
this.debug = debug; public Map<String, ResourceComparison> getCompares() {
} return compares;
}
public Map<String, ResourceComparison> getCompares() {
return compares;
}
} }

View File

@ -1,117 +1,118 @@
package org.hl7.fhir.r5.test; package org.hl7.fhir.r5.test;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.ArrayList;
import java.util.stream.Stream; import java.util.List;
import java.util.stream.Stream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.ParserConfigurationException;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.formats.IParser; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureMap; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.model.StructureMap;
import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.xml.XMLUtil; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.validation.ValidationEngine; import org.hl7.fhir.utilities.xml.XMLUtil;
import org.hl7.fhir.validation.instance.InstanceValidatorFactory; import org.hl7.fhir.validation.ValidationEngine;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest; import org.hl7.fhir.validation.instance.InstanceValidatorFactory;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.ParameterizedTest;
import org.w3c.dom.Document; import org.junit.jupiter.params.provider.Arguments;
import org.w3c.dom.Element; import org.junit.jupiter.params.provider.MethodSource;
import org.xml.sax.SAXException; import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class FHIRMappingLanguageTests { import org.xml.sax.SAXException;
private List<Resource> outputs = new ArrayList<Resource>(); public class FHIRMappingLanguageTests {
static private ValidationEngine validationEngine; private List<Resource> outputs = new ArrayList<Resource>();
static private SimpleWorkerContext context; static private ValidationEngine validationEngine;
public static Stream<Arguments> data() static private SimpleWorkerContext context;
throws FileNotFoundException, IOException, ParserConfigurationException, SAXException {
Document tests = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fml", "manifest.xml")); public static Stream<Arguments> data()
Element test = XMLUtil.getFirstChild(tests.getDocumentElement()); throws FileNotFoundException, IOException, ParserConfigurationException, SAXException {
List<Arguments> objects = new ArrayList<>(); Document tests = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fml", "manifest.xml"));
while (test != null && test.getNodeName().equals("test")) { Element test = XMLUtil.getFirstChild(tests.getDocumentElement());
objects.add(Arguments.of(test.getAttribute("name"), test.getAttribute("source"), test.getAttribute("map"), List<Arguments> objects = new ArrayList<>();
test.getAttribute("output"))); while (test != null && test.getNodeName().equals("test")) {
test = XMLUtil.getNextSibling(test); objects.add(Arguments.of(test.getAttribute("name"), test.getAttribute("source"), test.getAttribute("map"),
} test.getAttribute("output")));
return objects.stream(); test = XMLUtil.getNextSibling(test);
} }
return objects.stream();
@BeforeAll }
public static void setUp() throws Exception {
validationEngine = new ValidationEngine("hl7.fhir.r4.core#4.0.1"); @BeforeAll
context = validationEngine.getContext(); public static void setUp() throws Exception {
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "any.xml"), "any.xml", null); validationEngine = new ValidationEngine("hl7.fhir.r4.core#4.0.1");
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ii.xml"), "ii.xml", null); context = validationEngine.getContext();
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cd.xml"), "cd.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "any.xml"), "any.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ce.xml"), "ce.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ii.xml"), "ii.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cd.xml"), "cd.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ce.xml"), "ce.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null);
for (StructureDefinition sd : context.getStructures()) { context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null);
if (!sd.hasSnapshot()) { context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null);
System.out.println("generate snapshot for " + sd.getUrl()); for (StructureDefinition sd : context.getStructures()) {
context.generateSnapshot(sd, true); if (!sd.hasSnapshot()) {
} System.out.println("generate snapshot for " + sd.getUrl());
} context.generateSnapshot(sd, true);
if (context.getValidatorFactory() == null) { }
context.setValidatorFactory(new InstanceValidatorFactory()); }
} if (context.getValidatorFactory() == null) {
} context.setValidatorFactory(new InstanceValidatorFactory());
}
@ParameterizedTest(name = "{index}: {0}") }
@MethodSource("data")
public void test(String name, String source, String map, String output) throws Exception { @ParameterizedTest(name = "{index}: {0}")
@MethodSource("data")
byte[] byteSource = TestingUtilities.loadTestResourceBytes("r5", "fml", source); public void test(String name, String source, String map, String output) throws Exception {
String stringMap = TestingUtilities.loadTestResource("r5", "fml", map);
String outputJson = TestingUtilities.loadTestResource("r5", "fml", output); byte[] byteSource = TestingUtilities.loadTestResourceBytes("r5", "fml", source);
String fileOutputRes = TestingUtilities.tempFile("fml", output) + ".out"; String stringMap = TestingUtilities.loadTestResource("r5", "fml", map);
String fileOutputResOrig = TestingUtilities.tempFile("fml", output) + ".orig.out"; String outputJson = TestingUtilities.loadTestResource("r5", "fml", output);
ByteArrayOutputStream s = null; String fileOutputRes = TestingUtilities.tempFile("fml", output) + ".out";
outputs.clear(); String fileOutputResOrig = TestingUtilities.tempFile("fml", output) + ".orig.out";
ByteArrayOutputStream s = null;
String msg = null; outputs.clear();
try {
StructureMap r = new org.hl7.fhir.r5.utils.StructureMapUtilities(context).parse(stringMap, map); String msg = null;
context.cacheResource(r); try {
org.hl7.fhir.r5.elementmodel.Element element = validationEngine.transform(byteSource, FhirFormat.JSON, r.getUrl()); StructureMap r = new org.hl7.fhir.r5.utils.StructureMapUtilities(context).parse(stringMap, map);
s = new ByteArrayOutputStream(); context.cacheResource(r);
if (output.endsWith(".json")) org.hl7.fhir.r5.elementmodel.Element element = validationEngine.transform(byteSource, FhirFormat.JSON, r.getUrl());
new org.hl7.fhir.r5.elementmodel.JsonParser(context).compose(element, s, IParser.OutputStyle.PRETTY, null); s = new ByteArrayOutputStream();
else if (output.endsWith(".json"))
new org.hl7.fhir.r5.elementmodel.XmlParser(context).compose(element, s, IParser.OutputStyle.PRETTY, null); new org.hl7.fhir.r5.elementmodel.JsonParser(context).compose(element, s, IParser.OutputStyle.PRETTY, null);
context.dropResource(r); else
} catch (Exception e) { new org.hl7.fhir.r5.elementmodel.XmlParser(context).compose(element, s, IParser.OutputStyle.PRETTY, null);
assertTrue(e.getMessage(), false); context.dropResource(r);
} } catch (Exception e) {
if (output.endsWith("json")) { assertTrue(e.getMessage(), false);
msg = TestingUtilities.checkJsonSrcIsSame(s.toString(), outputJson); }
} else { if (output.endsWith("json")) {
TextFile.bytesToFile(s.toByteArray(), fileOutputRes); msg = TestingUtilities.checkJsonSrcIsSame(s.toString(), outputJson);
TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig); } else {
msg = TestingUtilities.checkXMLIsSame(new FileInputStream(fileOutputRes), new FileInputStream(fileOutputResOrig)); TextFile.bytesToFile(s.toByteArray(), fileOutputRes);
} TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig);
if (!Utilities.noString(msg)) { msg = TestingUtilities.checkXMLIsSame(new FileInputStream(fileOutputRes), new FileInputStream(fileOutputResOrig));
System.out.print(s.toString()); }
} if (!Utilities.noString(msg)) {
assertTrue(msg, Utilities.noString(msg)); System.out.print(s.toString());
} }
assertTrue(msg, Utilities.noString(msg));
}
} }