Merge pull request #56 from ahdis/oliveregger_maps3To4

unit test conversions r3r4
This commit is contained in:
Grahame Grieve 2019-07-06 07:21:02 +10:00 committed by GitHub
commit bc30ea197e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 62 deletions

View File

@ -289,6 +289,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
}
this.version = pi.version();
}
public void loadFromFile(String file, IContextResourceLoader loader) throws IOException, FHIRException {

View File

@ -73,8 +73,13 @@ public class XhtmlType extends Element {
@Override
public Base setProperty(int hash, String name, Base value) throws FHIRException {
if ("value".equals(name)) {
place.setDiv(castToXhtml(value));
return value;
if (value instanceof StringType) {
// div is already generated with getValue, we cannot just overwrite it
place.getDiv().setValueAsString(((StringType) value).asStringValue());
} else {
place.setDiv(castToXhtml(value));
}
return value;
} else
return super.setProperty(hash, name, value);
}

View File

@ -2889,7 +2889,7 @@ public class FHIRPathEngine {
if (!Utilities.noString(f)) {
if (exp.getParameters().size() != 2) {
if (exp.getParameters().size() == 2) {
String t = convertToString(execute(context, focus, exp.getParameters().get(0), true));
String r = convertToString(execute(context, focus, exp.getParameters().get(1), true));

View File

@ -1402,7 +1402,7 @@ public class StructureMapUtilities {
}
} else if (rule.getSource().size() == 1 && rule.getSourceFirstRep().hasVariable() && rule.getTarget().size() == 1 && rule.getTargetFirstRep().hasVariable() && rule.getTargetFirstRep().getTransform() == StructureMapTransform.CREATE && !rule.getTargetFirstRep().hasParameter()) {
// simple inferred, map by type
System.out.println(v.summary());
log(v.summary());
Base src = v.get(VariableMode.INPUT, rule.getSourceFirstRep().getVariable());
Base tgt = v.get(VariableMode.OUTPUT, rule.getTargetFirstRep().getVariable());
String srcType = src.fhirType();
@ -1493,7 +1493,9 @@ public class StructureMapUtilities {
if (value.contains("*")) {
for (StructureMap sm : worker.listTransforms()) {
if (urlMatches(value, sm.getUrl())) {
res.add(sm);
if (!res.contains(sm)) {
res.add(sm);
}
}
}
} else {

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.util.List;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -72,7 +73,12 @@ public class XhtmlType extends Element {
@Override
public Base setProperty(int hash, String name, Base value) throws FHIRException {
if ("value".equals(name)) {
place.setDiv(castToXhtml(value));
if (value instanceof StringType) {
// div is already generated with getValue, we cannot just overwrite it
place.getDiv().setValueAsString(((StringType) value).asStringValue());
} else {
place.setDiv(castToXhtml(value));
}
return value;
} else
return super.setProperty(hash, name, value);

View File

@ -2896,7 +2896,7 @@ public class FHIRPathEngine {
if (!Utilities.noString(f)) {
if (exp.getParameters().size() != 2) {
if (exp.getParameters().size() == 2) {
String t = convertToString(execute(context, focus, exp.getParameters().get(0), true));
String r = convertToString(execute(context, focus, exp.getParameters().get(1), true));

View File

@ -33,18 +33,20 @@ import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.ResourceFactory;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r4.test.utils.TestingUtilities;
import org.hl7.fhir.r4.model.StructureMap;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.test.utils.TestingUtilities;
import org.hl7.fhir.r4.utils.IResourceValidator;
import org.hl7.fhir.r4.utils.IResourceValidator.IValidatorResourceFetcher;
import org.hl7.fhir.r4.utils.IResourceValidator.ReferenceValidationPolicy;
import org.hl7.fhir.r4.utils.StructureMapUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.r5.validation.InstanceValidatorFactory;
import org.hl7.fhir.r4.validation.InstanceValidatorFactory;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.junit.Test;
@ -63,12 +65,14 @@ import com.google.gson.JsonPrimitive;
public class R3R4ConversionTests implements ITransformerServices, IValidatorResourceFetcher {
private static final boolean SAVING = true;
private PackageCacheManager pcm = null;
@Parameters(name = "{index}: id {0}")
public static Iterable<Object[]> data() throws ParserConfigurationException, SAXException, IOException {
if (!(new File(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")).exists()))
throw new Error("You must set the default directory to the build directory when you execute these tests");
r3r4Outcomes = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")));
r3r4Outcomes = (JsonObject) new com.google.gson.JsonParser().parse(
TextFile.fileToString(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")));
rules = new IniFile(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-rules.ini"));
String srcFile = Utilities.path(TestingUtilities.home(), "source", "release3", "examples.zip");
@ -79,7 +83,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
filter = filter.toLowerCase();
Map<String, byte[]> examples = new HashMap<String, byte[]>();
ZipEntry entry;
while((entry = stream.getNextEntry())!=null) {
while ((entry = stream.getNextEntry()) != null) {
String n = entry.getName();
byte[] buffer = new byte[2048];
ByteArrayOutputStream output = null;
@ -97,7 +101,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
List<Object[]> objects = new ArrayList<Object[]>(examples.size());
for (String id : names) {
objects.add(new Object[] { id, examples.get(id)});
objects.add(new Object[] { id, examples.get(id) });
}
return objects;
@ -137,7 +141,8 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
extras = new ArrayList<Resource>();
// load the example (r3)
org.hl7.fhir.r4.elementmodel.Element r3 = new org.hl7.fhir.r4.elementmodel.XmlParser(contextR3).parse(new ByteArrayInputStream(content));
org.hl7.fhir.r4.elementmodel.Element r3 = new org.hl7.fhir.r4.elementmodel.XmlParser(contextR3)
.parse(new ByteArrayInputStream(content));
tn = r3.fhirType();
workingid = r3.getChildValue("id");
if (SAVING) {
@ -145,13 +150,14 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
new org.hl7.fhir.r4.elementmodel.JsonParser(contextR3).compose(r3, bso, OutputStyle.PRETTY, null);
cnt = bso.toByteArray();
Utilities.createDirectory(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output"));
TextFile.bytesToFile(cnt, Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output", tn+"-"+workingid+".input.json"));
TextFile.bytesToFile(cnt, Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output",
tn + "-" + workingid + ".input.json"));
}
// load the r3 to R4 map
String mapFile = Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "R3toR4", r3.fhirType()+".map");
if (new File(mapFile).exists()) {
StructureMap sm = smu4.parse(TextFile.fileToString(mapFile), mapFile);
tn = smu4.getTargetType(sm).getType();
// convert from r3 to r4
@ -161,11 +167,13 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
ByteArrayOutputStream bs = new ByteArrayOutputStream();
new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(bs, r4);
if (SAVING) {
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output", tn+"-"+workingid+".r4.json"));
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps",
"test-output", tn + "-" + workingid + ".r4.json"));
for (Resource r : extras) {
bs = new ByteArrayOutputStream();
new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(bs, r);
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output", r.fhirType()+"-"+r.getId()+".r4.json"));
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps",
"test-output", r.fhirType() + "-" + r.getId() + ".r4.json"));
}
}
@ -176,8 +184,6 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
validator.validate(null, r4validationErrors, r4);
// load the R4 to R3 map
// mapFile = Utilities.path(root, "implementations", "r3maps", "R4toR3", r3.fhirType()+".map");
// s = sm.parse(TextFile.fileToString(mapFile));
mapFile = Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "R4toR3", getMapFor(r4.fhirType(), r3.fhirType())+".map");
sm = smu3.parse(TextFile.fileToString(mapFile), mapFile);
@ -190,15 +196,17 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
bs = new ByteArrayOutputStream();
new org.hl7.fhir.r4.elementmodel.JsonParser(contextR3).compose(ro3, bs, OutputStyle.PRETTY, null);
if (SAVING)
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "test-output", tn+"-"+workingid+".output.json"));
TextFile.bytesToFile(bs.toByteArray(), Utilities.path(TestingUtilities.home(), "implementations", "r3maps",
"test-output", tn + "-" + workingid + ".output.json"));
// check(errors, tn, workingid);
roundTripError = TestingUtilities.checkJsonSrcIsSame(new String(cnt), new String(bs.toByteArray()), filter != null);
if (roundTripError != null && roundTripError.equals(rules.getStringProperty(tn+"/"+workingid, "roundtrip")))
// check(errors, tn, workingid);
roundTripError = TestingUtilities.checkJsonSrcIsSame(new String(cnt), new String(bs.toByteArray()),
filter != null);
if (roundTripError != null && roundTripError.equals(rules.getStringProperty(tn + "/" + workingid, "roundtrip")))
roundTripError = null;
} else {
if (loadErrors.containsKey(r3.fhirType()+".map")) {
executionError = loadErrors.get(r3.fhirType()+".map");
if (loadErrors.containsKey(r3.fhirType() + ".map")) {
executionError = loadErrors.get(r3.fhirType() + ".map");
}
}
} catch (Exception e) {
@ -216,10 +224,11 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
if (r3.equals("ReferralRequest"))
return "ServiceRequestRR";
// if (r3.equals("ProcedureRequest"))
return "ServiceRequestPR";
return "ServiceRequestPR";
}
private void updateOutcomes(String tn, String id, Exception executionError, List<ValidationMessage> r4validationErrors, String roundTripError) throws IOException {
private void updateOutcomes(String tn, String id, Exception executionError,
List<ValidationMessage> r4validationErrors, String roundTripError) throws IOException {
JsonObject r = r3r4Outcomes.getAsJsonObject(tn);
if (r == null) {
r = new JsonObject();
@ -238,7 +247,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
i.addProperty("execution", true);
else
i.addProperty("execution", executionError.getMessage());
// round-trip check
// round-trip check
if (i.has("round-trip"))
i.remove("round-trip");
if (roundTripError != null)
@ -251,11 +260,12 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
JsonArray arr = new JsonArray();
i.add("r4.errors", arr);
for (ValidationMessage e : r4validationErrors)
arr.add(new JsonPrimitive(e.summary()));
arr.add(new JsonPrimitive(e.summary()));
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(r3r4Outcomes);
TextFile.stringToFile(json, (Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")));
TextFile.stringToFile(json,
(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "outcomes.json")));
}
@ -266,7 +276,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
break;
if (vm.getMessage().contains("Error null validating Coding"))
break;
String s = rules.getStringProperty(tn+"/"+id, "validation");
String s = rules.getStringProperty(tn + "/" + id, "validation");
if (!Utilities.noString(s)) {
boolean ok = false;
for (String m : s.split("\\;"))
@ -285,7 +295,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
break;
}
if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL) {
b.append("[R4 validation error] "+vm.getLocation()+": "+vm.getMessage()+"\r\n");
b.append("[R4 validation error] " + vm.getLocation() + ": " + vm.getMessage() + "\r\n");
}
}
if (b.length() > 0)
@ -293,32 +303,31 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
}
/*
* Supporting multiple versions at once is a little tricky. We're going to have 2 contexts:
* - an R3 context which is used to read/write R3 instances
* - an R4 context which is used to perform the transforms
* Supporting multiple versions at once is a little tricky. We're going to have
* 2 contexts: - an R3 context which is used to read/write R3 instances - an R4
* context which is used to perform the transforms
*
* R3 structure definitions are cloned into R3 context with a modified URL (as
* 3.0/)
*
* R3 structure definitions are cloned into R3 context with a modified URL (as 3.0/)
*
*/
private void checkLoad() throws IOException, FHIRException {
private void checkLoad() throws IOException, FHIRException, Exception {
if (contextR3 != null)
return;
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
R3ToR4Loader ldr = new R3ToR4Loader().setPatchUrls(true).setKillPrimitives(true);
System.out.println("loading R3");
contextR3 = new SimpleWorkerContext();
contextR3.setAllowLoadingDuplicates(true);
contextR3.setOverrideVersionNs("http://hl7.org/fhir/3.0/StructureDefinition");
contextR3.loadFromFile(Utilities.path(TestingUtilities.home(),"source","release3","profiles-types.xml"), ldr);
contextR3.loadFromFile(Utilities.path(TestingUtilities.home(),"source","release3","profiles-resources.xml"), ldr);
contextR3.loadFromFile(Utilities.path(TestingUtilities.home(),"source","release3","expansions.xml"), ldr);
contextR3.loadFromPackage(pcm.loadPackage("hl7.fhir.core", "3.0.1"), ldr, new String[] {});
System.out.println("loading R4");
contextR4 = new SimpleWorkerContext();
contextR4.setAllowLoadingDuplicates(true);
contextR4.loadFromFile(Utilities.path(TestingUtilities.content(),"profiles-types.xml"), null);
contextR4.loadFromFile(Utilities.path(TestingUtilities.content(),"profiles-resources.xml"), null);
contextR4.loadFromFile(Utilities.path(TestingUtilities.content(),"extension-definitions.xml"), null);
contextR4.loadFromFile(Utilities.path(TestingUtilities.content(),"valuesets.xml"), null);
contextR4 = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
contextR4.setCanRunWithoutTerminology(true);
for (StructureDefinition sd : contextR3.allStructures()) {
@ -332,7 +341,8 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
contextR3.cacheResource(sd);
StructureDefinition sdn = sd.copy();
sdn.setUrl(sdn.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/3.0/"));
sdn.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir"));
sdn.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace")
.setValue(new UriType("http://hl7.org/fhir"));
contextR3.cacheResource(sdn);
contextR4.cacheResource(sdn);
}
@ -342,11 +352,15 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
contextR4.setExpansionProfile(new org.hl7.fhir.r4.model.Parameters());
contextR3.setName("R3");
contextR4.setName("R4");
contextR4.setValidatorFactory(new InstanceValidatorFactory());
// TODO: this has to be R% now... contextR4.setValidatorFactory(new InstanceValidatorFactory());
System.out.println("loading Maps");
loadLib(Utilities.path(TestingUtilities.home(),"implementations","r3maps", "R3toR4"));
loadLib(Utilities.path(TestingUtilities.home(),"implementations","r3maps", "R4toR3"));
loadLib(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "R4toR3"));
loadLib(Utilities.path(TestingUtilities.home(), "implementations", "r3maps", "R3toR4"));
System.out.println("loaded");
}
@ -361,30 +375,31 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
for (Resource r : sm.getContained()) {
if (r instanceof MetadataResource) {
MetadataResource mr = (MetadataResource) r.copy();
mr.setUrl(sm.getUrl()+"#"+r.getId());
mr.setUrl(sm.getUrl() + "#" + r.getId());
contextR3.cacheResource(mr);
contextR4.cacheResource(mr);
}
}
} catch (FHIRException e) {
System.out.println("Unable to load "+Utilities.path(dir, s)+": "+e.getMessage());
System.out.println("Unable to load " + Utilities.path(dir, s) + ": " + e.getMessage());
loadErrors.put(s, e);
// e.printStackTrace();
// e.printStackTrace();
}
}
}
@Override
public void log(String message) {
System.out.println(message);
System.out.println(message);
}
@Override
public Base createResource(Object appInfo, Base res, boolean atRootofTransform) {
if (res instanceof Resource && (res.fhirType().equals("CodeSystem") || res.fhirType().equals("CareTeam")) || res.fhirType().equals("PractitionerRole")) {
if (res instanceof Resource && (res.fhirType().equals("CodeSystem") || res.fhirType().equals("CareTeam")
|| res.fhirType().equals("PractitionerRole"))) {
Resource r = (Resource) res;
extras.add(r);
r.setId(workingid+"-"+extras.size());
r.setId(workingid + "-" + extras.size());
}
return res;
}
@ -398,9 +413,10 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
public Base createType(Object appInfo, String name) throws FHIRException {
BaseWorkerContext context = (BaseWorkerContext) appInfo;
if (context == contextR3) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/3.0/StructureDefinition/"+name);
StructureDefinition sd = context.fetchResource(StructureDefinition.class,
"http://hl7.org/fhir/3.0/StructureDefinition/" + name);
if (sd == null)
throw new FHIRException("Type not found: '"+name+"'");
throw new FHIRException("Type not found: '" + name + "'");
return Manager.build(context, sd);
} else
return ResourceFactory.createResourceOrType(name);
@ -414,7 +430,7 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
if (url.equals(mr.getUrl()))
return mr;
}
if (url.equals(r.fhirType()+"/"+r.getId()))
if (url.equals(r.fhirType() + "/" + r.getId()))
return r;
}
@ -429,7 +445,8 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
String[] vals = parts[1].split("\\=");
if (vals.length == 2 && vals[0].equals("practitioner"))
for (Resource r : extras) {
if (r instanceof PractitionerRole && ((PractitionerRole) r).getPractitioner().getReference().equals("Practitioner/"+vals[1])) {
if (r instanceof PractitionerRole
&& ((PractitionerRole) r).getPractitioner().getReference().equals("Practitioner/" + vals[1])) {
results.add(r);
}
}
@ -438,7 +455,8 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
}
@Override
public Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, IOException, FHIRException {
public Element fetch(Object appContext, String url)
throws FHIRFormatError, DefinitionException, IOException, FHIRException {
return null;
}
@ -451,6 +469,4 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
return true;
}
}