This commit is contained in:
Grahame Grieve 2020-06-14 07:07:42 +10:00
commit 779d50b61b
22 changed files with 683 additions and 501 deletions

View File

@ -1,7 +0,0 @@
* Override extension methods in BackboneElement to look in modifierExtensions as well as extensions
* 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
* Improvements for CDA round-tripping (XML esacping issues, xsi:type related issues, namespacing issues)
* Fix bug rendering DiagnosticReports with multiple categories
* adjust check on Attachment to only be an warning (when no meaningful content exists)
* add security check mode to Validator

View File

@ -1,10 +1,6 @@
trigger:
- master
- release
trigger: none
pr:
- master
- release
pr: none
# Different users have different machine setups, we run the build three times, on ubuntu, osx, and windows
strategy:

View File

@ -0,0 +1,85 @@
# This pipeline produces a SNAPSHOT build for each of the sub modules in
# the core library, and publishes them to ossrh.
pr: none
trigger:
- master
pool:
vmImage: "ubuntu-16.04"
steps:
# Signing, for now, occurs for all builds, SNAPSHOT or release. So we need a valid
# signing key. The next two steps download the public and private keys from the
# secure library files.
- task: DownloadSecureFile@1
displayName: 'Download public key.'
inputs:
secureFile: public.key
- task: DownloadSecureFile@1
displayName: 'Download private key.'
inputs:
secureFile: private.key
# Import both the private and public keys into gpg for signing.
- bash: |
gpg --import --no-tty --batch --yes $(Agent.TempDirectory)/public.key
gpg --import --no-tty --batch --yes $(Agent.TempDirectory)/private.key
gpg --list-keys --keyid-format LONG
gpg --list-secret-keys --keyid-format LONG
displayName: 'Import signing keys.'
# For creating the snapshot release with maven, we need to build a fake settings.xml
# for it to read from. This is done for the master branch merges only.
- bash: |
cat >$(System.DefaultWorkingDirectory)/settings.xml <<EOL
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>ossrh</id>
<username>$(SONATYPE_USER)</username>
<password>$(SONATYPE_PASS)</password>
</server>
<server>
<id>sonatype-nexus-snapshots</id>
<username>$(SONATYPE_USER)</username>
<password>$(SONATYPE_PASS)</password>
</server>
<server>
<id>sonatype-nexus-staging</id>
<username>$(SONATYPE_USER)</username>
<password>$(SONATYPE_PASS)</password>
</server>
<server>
<id>$(PGP_KEYNAME)</id>
<passphrase>$(PGP_PASSPHRASE)</passphrase>
</server>
</servers>
<profiles>
<profile>
<id>release</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.keyname>$(PGP_KEYNAME)</gpg.keyname>
</properties>
</profile>
</profiles>
</settings>
EOL
displayName: 'Create .mvn/settings.xml'
# Deploy the SNAPSHOT artifact to sonatype nexus.
# This is done for the master branch merges only.
- task: Maven@3
displayName: 'Deploy $(module) to Sonatype staging'
inputs:
mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml'
goals: deploy
options: '--settings $(System.DefaultWorkingDirectory)/settings.xml'
publishJUnitResults: false

View File

@ -1,10 +1,6 @@
# This pipeline produces a SNAPSHOT build for each of the sub modules in
# the core library, and publishes them to ossrh.
trigger:
branches:
include:
- master
trigger: none
pr: none
pool:

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -2778,7 +2778,7 @@ public class VersionConvertor_30_40 {
return null;
org.hl7.fhir.r4.model.Timing tgt = new org.hl7.fhir.r4.model.Timing();
copyElement(src, tgt);
for (org.hl7.fhir.dstu3.model.DateTimeType t : src.getEvent()) tgt.addEvent(t.getValue());
for (org.hl7.fhir.dstu3.model.DateTimeType t : src.getEvent()) tgt.addEventElement().setValueAsString(t.getValueAsString());
if (src.hasRepeat())
tgt.setRepeat(convertTimingRepeatComponent(src.getRepeat()));
if (src.hasCode())
@ -2791,7 +2791,7 @@ public class VersionConvertor_30_40 {
return null;
org.hl7.fhir.dstu3.model.Timing tgt = new org.hl7.fhir.dstu3.model.Timing();
copyElement(src, tgt);
for (org.hl7.fhir.r4.model.DateTimeType t : src.getEvent()) tgt.addEvent(t.getValue());
for (org.hl7.fhir.r4.model.DateTimeType t : src.getEvent()) tgt.addEventElement().setValueAsString(t.getValueAsString());
if (src.hasRepeat())
tgt.setRepeat(convertTimingRepeatComponent(src.getRepeat()));
if (src.hasCode())

View File

@ -176,13 +176,13 @@ public class VersionConvertor_40_50 {
}
public static org.hl7.fhir.r5.model.DateTimeType convertDateTime(org.hl7.fhir.r4.model.DateTimeType src) throws FHIRException {
org.hl7.fhir.r5.model.DateTimeType tgt = src.hasValue() ? new org.hl7.fhir.r5.model.DateTimeType(src.getValue()) : new org.hl7.fhir.r5.model.DateTimeType();
org.hl7.fhir.r5.model.DateTimeType tgt = src.hasValue() ? new org.hl7.fhir.r5.model.DateTimeType(src.getValueAsString()) : new org.hl7.fhir.r5.model.DateTimeType();
copyElement(src, tgt);
return tgt;
}
public static org.hl7.fhir.r4.model.DateTimeType convertDateTime(org.hl7.fhir.r5.model.DateTimeType src) throws FHIRException {
org.hl7.fhir.r4.model.DateTimeType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.DateTimeType(src.getValue()) : new org.hl7.fhir.r4.model.DateTimeType();
org.hl7.fhir.r4.model.DateTimeType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.DateTimeType(src.getValueAsString()) : new org.hl7.fhir.r4.model.DateTimeType();
copyElement(src, tgt);
return tgt;
}
@ -218,31 +218,31 @@ public class VersionConvertor_40_50 {
}
public static org.hl7.fhir.r4.model.InstantType convertInstant(org.hl7.fhir.r5.model.InstantType src) throws FHIRException {
org.hl7.fhir.r4.model.InstantType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.InstantType(src.getValue()) : new org.hl7.fhir.r4.model.InstantType();
org.hl7.fhir.r4.model.InstantType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.InstantType(src.getValueAsString()) : new org.hl7.fhir.r4.model.InstantType();
copyElement(src, tgt);
return tgt;
}
public static org.hl7.fhir.r5.model.IntegerType convertInteger(org.hl7.fhir.r4.model.IntegerType src) throws FHIRException {
org.hl7.fhir.r5.model.IntegerType tgt = src.hasValue() ? new org.hl7.fhir.r5.model.IntegerType(src.getValue()) : new org.hl7.fhir.r5.model.IntegerType();
org.hl7.fhir.r5.model.IntegerType tgt = src.hasValue() ? new org.hl7.fhir.r5.model.IntegerType(src.getValueAsString()) : new org.hl7.fhir.r5.model.IntegerType();
copyElement(src, tgt);
return tgt;
}
public static org.hl7.fhir.r5.model.Integer64Type convertUnsignedIntToInteger64(org.hl7.fhir.r4.model.UnsignedIntType src) throws FHIRException {
org.hl7.fhir.r5.model.Integer64Type tgt = src.hasValue() ? new org.hl7.fhir.r5.model.Integer64Type(Long.valueOf(src.getValue())) : new org.hl7.fhir.r5.model.Integer64Type();
org.hl7.fhir.r5.model.Integer64Type tgt = src.hasValue() ? new org.hl7.fhir.r5.model.Integer64Type(src.getValueAsString()) : new org.hl7.fhir.r5.model.Integer64Type();
copyElement(src, tgt);
return tgt;
}
public static org.hl7.fhir.r4.model.UnsignedIntType convertInteger64ToUnsignedInt(org.hl7.fhir.r5.model.Integer64Type src) throws FHIRException {
org.hl7.fhir.r4.model.UnsignedIntType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.UnsignedIntType(Math.toIntExact(src.getValue())) : new org.hl7.fhir.r4.model.UnsignedIntType();
org.hl7.fhir.r4.model.UnsignedIntType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.UnsignedIntType(src.getValueAsString()) : new org.hl7.fhir.r4.model.UnsignedIntType();
copyElement(src, tgt);
return tgt;
}
public static org.hl7.fhir.r4.model.IntegerType convertInteger(org.hl7.fhir.r5.model.IntegerType src) throws FHIRException {
org.hl7.fhir.r4.model.IntegerType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.IntegerType(src.getValue()) : new org.hl7.fhir.r4.model.IntegerType();
org.hl7.fhir.r4.model.IntegerType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.IntegerType(src.getValueAsString()) : new org.hl7.fhir.r4.model.IntegerType();
copyElement(src, tgt);
return tgt;
}
@ -3654,10 +3654,10 @@ public class VersionConvertor_40_50 {
return convertTime((org.hl7.fhir.r4.model.TimeType) src);
if (src instanceof org.hl7.fhir.r4.model.UrlType)
return convertUrl((org.hl7.fhir.r4.model.UrlType) src);
if (src instanceof org.hl7.fhir.r4.model.UuidType)
return convertUuid((org.hl7.fhir.r4.model.UuidType) src);
if (src instanceof org.hl7.fhir.r4.model.UriType)
return convertUri((org.hl7.fhir.r4.model.UriType) src);
if (src instanceof org.hl7.fhir.r4.model.UuidType)
return convertUuid((org.hl7.fhir.r4.model.UuidType) src);
if (src instanceof org.hl7.fhir.r4.model.Extension)
return convertExtension((org.hl7.fhir.r4.model.Extension) src);
if (src instanceof org.hl7.fhir.r4.model.Narrative)
@ -3712,6 +3712,10 @@ public class VersionConvertor_40_50 {
return convertProdCharacteristic((org.hl7.fhir.r4.model.ProdCharacteristic) src);
if (src instanceof org.hl7.fhir.r4.model.ProductShelfLife)
return convertProductShelfLife((org.hl7.fhir.r4.model.ProductShelfLife) src);
if (src instanceof org.hl7.fhir.r4.model.MoneyQuantity)
return convertMoneyQuantity((org.hl7.fhir.r4.model.MoneyQuantity) src);
if (src instanceof org.hl7.fhir.r4.model.SimpleQuantity)
return convertSimpleQuantity((org.hl7.fhir.r4.model.SimpleQuantity) src);
if (src instanceof org.hl7.fhir.r4.model.Quantity)
return convertQuantity((org.hl7.fhir.r4.model.Quantity) src);
if (src instanceof org.hl7.fhir.r4.model.Range)
@ -3736,10 +3740,6 @@ public class VersionConvertor_40_50 {
return convertUsageContext((org.hl7.fhir.r4.model.UsageContext) src);
if (src instanceof org.hl7.fhir.r4.model.ElementDefinition)
return convertElementDefinition((org.hl7.fhir.r4.model.ElementDefinition) src);
if (src instanceof org.hl7.fhir.r4.model.MoneyQuantity)
return convertMoneyQuantity((org.hl7.fhir.r4.model.MoneyQuantity) src);
if (src instanceof org.hl7.fhir.r4.model.SimpleQuantity)
return convertSimpleQuantity((org.hl7.fhir.r4.model.SimpleQuantity) src);
throw new Error("Unknown type " + src.fhirType());
}
@ -3780,10 +3780,10 @@ public class VersionConvertor_40_50 {
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.UrlType)
return convertUrl((org.hl7.fhir.r5.model.UrlType) src);
if (src instanceof org.hl7.fhir.r5.model.UuidType)
return convertUuid((org.hl7.fhir.r5.model.UuidType) src);
if (src instanceof org.hl7.fhir.r5.model.UriType)
return convertUri((org.hl7.fhir.r5.model.UriType) src);
if (src instanceof org.hl7.fhir.r5.model.UuidType)
return convertUuid((org.hl7.fhir.r5.model.UuidType) src);
if (src instanceof org.hl7.fhir.r5.model.Extension)
return convertExtension((org.hl7.fhir.r5.model.Extension) src);
if (src instanceof org.hl7.fhir.r5.model.Narrative)
@ -3838,6 +3838,10 @@ public class VersionConvertor_40_50 {
return convertProdCharacteristic((org.hl7.fhir.r5.model.ProdCharacteristic) src);
if (src instanceof org.hl7.fhir.r5.model.ProductShelfLife)
return convertProductShelfLife((org.hl7.fhir.r5.model.ProductShelfLife) src);
if (src instanceof org.hl7.fhir.r5.model.MoneyQuantity)
return convertMoneyQuantity((org.hl7.fhir.r5.model.MoneyQuantity) src);
if (src instanceof org.hl7.fhir.r5.model.SimpleQuantity)
return convertSimpleQuantity((org.hl7.fhir.r5.model.SimpleQuantity) src);
if (src instanceof org.hl7.fhir.r5.model.Quantity)
return convertQuantity((org.hl7.fhir.r5.model.Quantity) src);
if (src instanceof org.hl7.fhir.r5.model.Range)
@ -3862,10 +3866,6 @@ public class VersionConvertor_40_50 {
return convertUsageContext((org.hl7.fhir.r5.model.UsageContext) src);
if (src instanceof org.hl7.fhir.r5.model.ElementDefinition)
return convertElementDefinition((org.hl7.fhir.r5.model.ElementDefinition) src);
if (src instanceof org.hl7.fhir.r5.model.MoneyQuantity)
return convertMoneyQuantity((org.hl7.fhir.r5.model.MoneyQuantity) src);
if (src instanceof org.hl7.fhir.r5.model.SimpleQuantity)
return convertSimpleQuantity((org.hl7.fhir.r5.model.SimpleQuantity) src);
throw new Error("Unknown type " + src.fhirType());
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1,212 +1,213 @@
package org.hl7.fhir.r5.comparison;
import java.io.FileOutputStream;
import java.io.IOException;
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.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison;
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.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.Tuple;
import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.LiquidEngine;
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
public class ComparisonRenderer implements IEvaluationContext {
private IWorkerContext context;
private ComparisonSession session;
private Map<String, String> templates = new HashMap<>();
private String folder;
public ComparisonRenderer(IWorkerContext context, String folder, ComparisonSession session) {
super();
this.context = context;
this.folder = folder;
this.session = session;
}
public Map<String, String> getTemplates() {
return templates;
}
public void render() throws IOException {
dumpBinaries();
StringBuilder b = new StringBuilder();
for (String id : sorted(session.getCompares().keySet())) {
ResourceComparison comp = session.getCompares().get(id);
renderComparison(id, comp);
b.append("<li><a href=\""+comp.getId()+".html\">"+Utilities.escapeXml(comp.summary())+"</a></li>\r\n");
}
Map<String, Base> vars = new HashMap<>();
CodeSystemComparer cs = new CodeSystemComparer(session);
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);
TextFile.stringToFile(cnt, file("index.html"));
}
private List<String> sorted(Set<String> keySet) {
List<String> list = new ArrayList<>();
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 renderComparison(String id, ResourceComparison comp) throws IOException {
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);
}
}
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException {
String template = templates.get("CodeSystem");
Map<String, Base> 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("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);
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() + "-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 void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException {
String template = templates.get("ValueSet");
Map<String, Base> 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("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);
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() + "-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");
Map<String, Base> vars = new HashMap<>();
ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContext(), null, null));
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 cnt = processTemplate(template, "CodeSystem", vars);
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() + "-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);
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 {
@SuppressWarnings("unchecked")
Map<String, Base> vars = (Map<String, Base>) appContext;
return vars.get(name);
}
@Override
public TypeDetails resolveConstantType(Object appContext, String name) throws PathEngineException {
@SuppressWarnings("unchecked")
Map<String, Base> vars = (Map<String, Base>) appContext;
Base b = vars.get(name);
return new TypeDetails(CollectionStatus.SINGLETON, b == null ? "Base" : b.fhirType());
}
@Override
public boolean log(String argument, List<Base> focus) {
return false;
}
@Override
public FunctionDetails resolveFunction(String functionName) {
return null;
}
@Override
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) {
return null;
}
@Override
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 {
return false;
}
@Override
public ValueSet resolveValueSet(Object appContext, String url) {
return null;
}
}
package org.hl7.fhir.r5.comparison;
import java.io.FileOutputStream;
import java.io.IOException;
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.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison;
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.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.Tuple;
import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.LiquidEngine;
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
public class ComparisonRenderer implements IEvaluationContext {
private IWorkerContext context;
private ComparisonSession session;
private Map<String, String> templates = new HashMap<>();
private String folder;
public ComparisonRenderer(IWorkerContext context, String folder, ComparisonSession session) {
super();
this.context = context;
this.folder = folder;
this.session = session;
}
public Map<String, String> getTemplates() {
return templates;
}
public void render() throws IOException {
dumpBinaries();
StringBuilder b = new StringBuilder();
for (String id : sorted(session.getCompares().keySet())) {
ResourceComparison comp = session.getCompares().get(id);
renderComparison(id, comp);
b.append("<li><a href=\""+comp.getId()+".html\">"+Utilities.escapeXml(comp.summary())+"</a></li>\r\n");
}
Map<String, Base> vars = new HashMap<>();
CodeSystemComparer cs = new CodeSystemComparer(session);
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);
TextFile.stringToFile(cnt, file("index.html"));
}
private List<String> sorted(Set<String> keySet) {
List<String> list = new ArrayList<>();
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 renderComparison(String id, ResourceComparison comp) throws IOException {
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);
}
}
private void renderCodeSystem(String id, CodeSystemComparison comp) throws IOException {
String template = templates.get("CodeSystem");
Map<String, Base> 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("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);
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() + "-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 void renderValueSet(String id, ValueSetComparison comp) throws FHIRException, IOException {
String template = templates.get("ValueSet");
Map<String, Base> 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("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);
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() + "-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");
Map<String, Base> vars = new HashMap<>();
ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContext(), null, null));
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 cnt = processTemplate(template, "CodeSystem", vars);
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() + "-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);
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 {
@SuppressWarnings("unchecked")
Map<String, Base> vars = (Map<String, Base>) appContext;
return vars.get(name);
}
@Override
public TypeDetails resolveConstantType(Object appContext, String name) throws PathEngineException {
@SuppressWarnings("unchecked")
Map<String, Base> vars = (Map<String, Base>) appContext;
Base b = vars.get(name);
return new TypeDetails(CollectionStatus.SINGLETON, b == null ? "Base" : b.fhirType());
}
@Override
public boolean log(String argument, List<Base> focus) {
return false;
}
@Override
public FunctionDetails resolveFunction(String functionName) {
return null;
}
@Override
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) {
return null;
}
@Override
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 {
return false;
}
@Override
public ValueSet resolveValueSet(Object appContext, String url) {
return null;
}
}

View File

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

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

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

View File

@ -13,7 +13,7 @@
each other. It is fine to bump the point version of this POM without affecting
HAPI FHIR.
-->
<version>5.0.7-SNAPSHOT</version>
<version>5.0.8-SNAPSHOT</version>
<properties>
<hapi_fhir_version>5.0.0</hapi_fhir_version>
@ -73,7 +73,6 @@
</repositories>
<dependencies>
<!-- Use logback for tests -->
<dependency>
<groupId>ch.qos.logback</groupId>
@ -81,7 +80,6 @@
<version>1.2.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>

51
pull-request-pipeline.yml Normal file
View File

@ -0,0 +1,51 @@
trigger: none
pr:
- master
- release
# Different users have different machine setups, we run the build three times, on ubuntu, osx, and windows
strategy:
matrix:
linux:
imageName: 'ubuntu-latest'
mac:
imageName: "macos-10.15"
windows:
imageName: "windows-2019"
maxParallel: 3
pool:
vmImage: $(imageName)
variables:
currentImage: $(imageName)
codecov: $(CODECOV_TOKEN)
VERSION:
steps:
# Runs 'mvn clean package'
- task: Maven@3
inputs:
mavenPomFile: 'pom.xml'
mavenOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
goals: 'package'
# Upload test results to codecov
- script: bash <(curl https://codecov.io/bash) -t $(codecov)
displayName: 'codecov Bash Uploader'
condition: eq(variables.currentImage, 'ubuntu-latest')
# Publishes the test results to build artifacts.
- task: PublishCodeCoverageResults@1
displayName: 'Publish JaCoCo test results'
condition: eq(variables.currentImage, 'ubuntu-latest')
inputs:
codeCoverageTool: 'JaCoCo'
summaryFileLocation: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.report/target/site/jacoco-aggregate/jacoco.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.report/target/site/jacoco-aggregate/'

View File

@ -0,0 +1,69 @@
trigger:
- release
pr: none
pool:
vmImage: "ubuntu-16.04"
variables:
VERSION:
steps:
# This task pulls the <version> value from the org.hl7.fhir.r5 project pom.xml file. All modules are released as
# the same version, at the same time, as defined in the root level pom.xml.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
[xml]$pomXml = Get-Content -Path .\pom.xml
# version
Write-Host $pomXml.project.version
$version=$pomXml.project.version
Write-Host "##vso[task.setvariable variable=version]$version"
# Prints out the build version, for debugging purposes
- bash: echo Pulled version from pom.xml => $(version)
# Azure pipelines cannot pass variables between pipelines, but it can pass files, so we
# pass the build id (ex: 1.1.13-SNAPSHOT) as a string in a file.
# This is used in the release pipeline, so we create it here.
- bash: |
echo $(version)
VERSION=$(version)
echo "$VERSION" > $(System.DefaultWorkingDirectory)/VERSION
# Copies the VERSION file containing the build id (ex: 1.1.13-SNAPSHOT) to the staging directory
# This is done for release versions only.
- task: CopyFiles@2
displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
inputs:
SourceFolder: '$(System.Defaultworkingdirectory)'
Contents: "$(System.DefaultWorkingDirectory)/VERSION"
TargetFolder: '$(build.artifactstagingdirectory)'
# Runs 'mvn clean package'
- task: Maven@3
inputs:
mavenPomFile: 'pom.xml'
mavenOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: true
testResultsFiles: '**/surefire-reports/TEST-*.xml'
goals: 'package'
# Publishes the built Validator jar to build artifacts. Primarily for testing and debugging builds.
- task: PublishPipelineArtifact@1
displayName: 'Publish Validator jar'
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/org.hl7.fhir.validation/target/org.hl7.fhir.validation-$(version).jar"
artifactName: Validator
# Publishes the files we've moved into the staging directory, so they can be accessed by the
# release pipeline.
- task: PublishBuildArtifacts@1
displayName: 'Publish Build Artifacts'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'