Release v5.0.6 (#226)

* reenable test and fix recursion

* remove disabled r4 fml tests

* add conformsTo test and support for FML

* Snapshot builder fix (#223)

* Update module-snapshot-publishing.yml for Azure Pipelines

* Changing pipeline, because intermodule depenedecies are not being read in correctly.

* Update README.md

* Fixed bad link

* Release: v5.0.6

***NO_CI***

* Updating version to: 5.0.7-SNAPSHOT
***NO_CI***

* Fixing issues and preparing for release (#225)

* Issue #189 - improve Questionnaire error message

* fix for issue #187

* more work on comparison

* Fix for NamingSystem display

Co-authored-by: Oliver Egger <oliver.egger@ahdis.ch>
Co-authored-by: Grahame Grieve <grahameg@gmail.com>
This commit is contained in:
Mark Iantorno 2020-06-05 18:47:17 -04:00 committed by GitHub
parent 8588b801b5
commit 0fb57007c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 334 additions and 367 deletions

View File

@ -1,26 +1,97 @@
HAPI FHIR - HL7 FHIR Core Artifacts
===================================
# HAPI FHIR - HL7 FHIR Core Artifacts
[![Build Status](https://travis-ci.org/hapifhir/org.hl7.fhir.core.svg?branch=master)](https://travis-ci.org/hapifhir/org.hl7.fhir.core)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/hapifhir/org.hl7.fhir.core/badge.svg)](http://search.maven.org/#search|ga|1|hapifhir/org.hl7.fhir.core)
### CI/CD
| master Branch CI | SNAPSHOT Publisher |
| :---: | :---: |
| [![Build Status][Badge-BuildPipeline]][Link-BuildPipeline] | [![Build Status][Badge-SnapshotPipeline]][Link-SnapshotPipeline] |
All intergration and delivery done on Azure pipelines. Every successful merge to master branch will result in a new SNAPSHOT build being published to Sonatype. Azure project can be viewed [here][Link-AzureProject].
# Building this Project
### Current Versions
| Project | Latest SNAPSHOT | Current Release |
| :---: | :---: | :---: |
| org.hl7.fhir.validation.cli | [![Snapshot Artifact][Badge-cliSonatypeSnapshot]][Link-cliSonatypeSnapshot] | [![Release Artifacts][Badge-cliSonatypeRelease]][Link-cliSonatypeRelease] |
| org.hl7.fhir.r4 | [![Snapshot Artifact][Badge-r4SonatypeSnapshot]][Link-r4SonatypeSnapshot] | [![Release Artifacts][Badge-r4SonatypeRelease]][Link-r4SonatypeRelease] |
| org.hl7.fhir.r5 | [![Snapshot Artifact][Badge-r5SonatypeSnapshot]][Link-r5SonatypeSnapshot] | [![Release Artifacts][Badge-r5SonatypeRelease]][Link-r5SonatypeRelease] |
### Building this Project
This project uses [Apache Maven](http://maven.apache.org) to build. To build:
```
mvn install
```
Note that unit tests will run, but are currently not set to fail the build as they do not all pass. This is being worked on.
To skip unit tests:
```
mvn -Dmaven.test.skip install
```
== Maintenance
### Download
##### org.hl7.fhir.validation.cli
###### Maven
```xml
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.validation.cli</artifactId>
<version>(latest version)</version>
</dependency>
```
This project is maintained by Grahame Grieve and James Agnew on behalf of the FHIR community.
###### Gradle
```groovy
compile group: 'ca.uhn.hapi.fhir', name: 'org.hl7.fhir.validation.cli', version: '(latest version)'
```
##### org.hl7.fhir.r4
###### Maven
```xml
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-r4</artifactId>
<version>(latest version)</version>
</dependency>
```
###### Gradle
```groovy
compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r4', version: '(latest version)'
```
##### org.hl7.fhir.r5
###### Maven
```xml
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-r5</artifactId>
<version>(latest version)</version>
</dependency>
```
###### Gradle
```groovy
compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r5', version: '(latest version)'
```
### Maintenance
This project is maintained by [Grahame Grieve][Link-grahameGithub] and [James Agnew][Link-jamesGithub] on behalf of the FHIR community.
[Link-AzureProject]: https://dev.azure.com/fhir-pipelines/fhir-core-library
[Link-BuildPipeline]: https://dev.azure.com/fhir-pipelines/fhir-core-library/_build/latest?definitionId=16&branchName=master
[Link-SnapshotPipeline]: https://dev.azure.com/fhir-pipelines/fhir-core-library/_build/latest?definitionId=17&branchName=master
[Link-r4SonatypeSnapshot]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.r4&v=LATEST "Sonatype Snapshot"
[Link-r4SonatypeRelease]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.r4&v=LATEST "Sonatype Release"
[Link-r5SonatypeSnapshot]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.r5&v=LATEST "Sonatype Snapshot"
[Link-r5SonatypeRelease]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.r5&v=LATEST "Sonatype Release"
[Link-cliSonatypeSnapshot]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=LATEST "Sonatype Snapshot"
[Link-cliSonatypeRelease]: https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=LATEST "Sonatype Release"
[Link-grahameGithub]: https://github.com/grahamegrieve
[Link-jamesGithub]: https://github.com/jamesagnew
[Badge-BuildPipeline]: https://dev.azure.com/fhir-pipelines/fhir-core-library/_apis/build/status/Build%20%26%20Test?branchName=master
[Badge-SnapshotPipeline]: https://dev.azure.com/fhir-pipelines/fhir-core-library/_apis/build/status/Module%20SNAPSHOT%20Publisher?branchName=master
[Badge-r4SonatypeRelease]: https://img.shields.io/nexus/r/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.r4.svg "Sonatype Releases"
[Badge-r4SonatypeSnapshot]: https://img.shields.io/nexus/s/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.r4.svg "Sonatype Snapshots"
[Badge-r5SonatypeRelease]: https://img.shields.io/nexus/r/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.r5.svg "Sonatype Releases"
[Badge-r5SonatypeSnapshot]: https://img.shields.io/nexus/s/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.r5.svg "Sonatype Snapshots"
[Badge-cliSonatypeRelease]: https://img.shields.io/nexus/r/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.validation.cli.svg "Sonatype Releases"
[Badge-cliSonatypeSnapshot]: https://img.shields.io/nexus/s/https/oss.sonatype.org/ca.uhn.hapi.fhir/org.hl7.fhir.validation.cli.svg "Sonatype Snapshots"

View File

@ -1 +0,0 @@

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1,149 +0,0 @@
package org.hl7.fhir.r4.test;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.context.SimpleWorkerContext;
import org.hl7.fhir.r4.elementmodel.Manager;
import org.hl7.fhir.r4.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
import org.hl7.fhir.r4.formats.JsonParser;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r4.terminologies.ConceptMapEngine;
import org.hl7.fhir.r4.test.utils.TestingUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
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;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertTrue;
@Disabled
public class FHIRMappingLanguageTests implements ITransformerServices {
private List<Resource> outputs = new ArrayList<Resource>();
static private SimpleWorkerContext context;
static private JsonParser jsonParser;
public static Stream<Arguments> data()
throws FileNotFoundException, IOException, ParserConfigurationException, SAXException {
Document tests = XMLUtil.parseFileToDom(TestingUtilities.resourceNameToFile("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
static public void setUp() throws Exception {
if (context == null) {
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);
}
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("data")
public void test(String name, String source, String map, String output) throws Exception {
String fileSource = TestingUtilities.resourceNameToFile("fml", source);
String fileMap = TestingUtilities.resourceNameToFile("fml", map);
String fileOutput = TestingUtilities.resourceNameToFile("fml", output);
String fileOutputRes = TestingUtilities.resourceNameToFile("fml", output) + ".out";
outputs.clear();
boolean ok = false;
String msg = null;
Resource resource = null;
try {
StructureMapUtilities scu = new StructureMapUtilities(context, this);
org.hl7.fhir.r4.elementmodel.Element src = Manager.parse(context,
new ByteArrayInputStream(TextFile.fileToBytes(fileSource)), FhirFormat.JSON);
StructureMap structureMap = scu.parse(TextFile.fileToString(fileMap), name);
String typeName = scu.getTargetType(structureMap).getType();
resource = ResourceFactory.createResource(typeName);
scu.transform(null, src, structureMap, resource);
ok = true;
} catch (Exception e) {
ok = false;
msg = e.getMessage();
}
if (ok) {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
jsonParser.compose(boas, resource);
log(boas.toString());
TextFile.bytesToFile(boas.toByteArray(), fileOutputRes);
msg = TestingUtilities.checkJsonIsSame(fileOutputRes, fileOutput);
assertTrue(msg, Utilities.noString(msg));
} else
assertTrue("Error, but proper output was expected (" + msg + ")", output.equals("$error"));
}
@Override
public void log(String message) {
System.out.println(message);
}
@Override
public Base createType(Object appInfo, String name) throws FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, name);
if (sd != null && sd.getKind() == StructureDefinitionKind.LOGICAL) {
return Manager.build(context, sd);
} else {
if (name.startsWith("http://hl7.org/fhir/StructureDefinition/"))
name = name.substring("http://hl7.org/fhir/StructureDefinition/".length());
return ResourceFactory.createResourceOrType(name);
}
}
@Override
public Base createResource(Object appInfo, Base res, boolean atRootofTransform) {
if (atRootofTransform)
outputs.add((Resource) res);
return res;
}
@Override
public Coding translate(Object appInfo, Coding source, String conceptMapUrl) throws FHIRException {
ConceptMapEngine cme = new ConceptMapEngine(context);
return cme.translate(source, conceptMapUrl);
}
@Override
public Base resolveReference(Object appContext, String url) throws FHIRException {
throw new FHIRException("resolveReference is not supported yet");
}
@Override
public List<Base> performSearch(Object appContext, String url) throws FHIRException {
throw new FHIRException("performSearch is not supported yet");
}
}

View File

@ -1 +0,0 @@
*.out

View File

@ -1,6 +0,0 @@
<fml-tests>
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" source="qr.json" map="qr2pat-assignment.map" output="qr2pat-assignment-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" source="qr.json" map="qr2pat-gender.map" output="qr2pat-gender-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" source="qr.json" map="qr2pat-humannametwice.map" output="qr2pat-humannametwice-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" source="qr.json" map="qr2pat-humannameshared.map" output="qr2pat-humannameshared-res.json" />
</fml-tests>

View File

@ -1,39 +0,0 @@
{
"resourceType": "QuestionnaireResponse",
"status": "in-progress",
"item": [
{
"linkId": "patient",
"text": "Patient",
"item": [
{
"linkId": "patient.lastname",
"text": "Name",
"answer": [
{
"valueString": "Brönnimann-Bertholet"
}
]
},
{
"linkId": "patient.firstname",
"text": "Vorname",
"answer": [
{
"valueString": "Elisabeth"
}
]
},
{
"linkId": "patient.sex",
"text": "Geschlecht",
"answer": [
{
"valueString": "female"
}
]
}
]
}
]
}

View File

@ -1,4 +0,0 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -1,8 +0,0 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" = "qr2patassignment"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src -> tgt.gender = 'female' "Simple Assignment";
}

View File

@ -1,4 +0,0 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -1,12 +0,0 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" = "qr2patgender"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item -> tgt as patient then item(item, patient);
}
group item(source src, target tgt: Patient) {
src.item as item where linkId.value in ('patient.sex') -> tgt.gender = (item.answer.valueString);
}

View File

@ -1,8 +0,0 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet",
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -1,26 +0,0 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name share patientName then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name share patientName then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

@ -1,10 +0,0 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet"
},
{
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -1,26 +0,0 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

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

View File

@ -226,7 +226,6 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
}
}
private boolean hasDesignation(ConceptDefinitionDesignationComponent td, List<ConceptDefinitionDesignationComponent> designation) {
for (ConceptDefinitionDesignationComponent t : designation) {
if (designationsMatch(td, t)) {
@ -303,7 +302,6 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
return null;
}
public XhtmlNode renderConcepts(CodeSystemComparison comparison, String id, String prefix) throws FHIRException, IOException {
// columns: code, display (left|right), properties (left|right)
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(Utilities.path("[tmp]", "compare"), false);

View File

@ -0,0 +1,166 @@
package org.hl7.fhir.r5.comparison;
import java.awt.image.renderable.RenderContext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.StructureDefinition;
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) {
super();
this.context = context;
this.folder = folder;
}
public Map<String, String> getTemplates() {
return templates;
}
public void render() throws IOException {
for (String id : session.getCompares().keySet()) {
renderComparison(id, session.getCompares().get(id));
}
}
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("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(id+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-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("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("expnsion", new StringType(new XhtmlComposer(true).compose(cs.renderExpansion(comp, "", ""))));
String cnt = processTemplate(template, "ValueSet", vars);
TextFile.stringToFile(cnt, file(id+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-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);
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(id+".html"));
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-union.json")), comp.getUnion());
new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", id + "-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, null, 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

@ -25,6 +25,7 @@ public class ComparisonSession {
private IWorkerContext context;
private String sessiondId;
private int count;
private boolean debug;
public ComparisonSession(IWorkerContext context) {
super();
@ -90,6 +91,22 @@ public class ComparisonSession {
public void identify(ResourceComparison res) {
count++;
res.setId(sessiondId+"-"+count);
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public Map<String, ResourceComparison> getCompares() {
return compares;
}
}

View File

@ -113,6 +113,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
assert(right != null);
assert(left.path().equals(right.path()));
if (session.isDebug()) {
System.out.println("Compare elements at "+path);
}
// not allowed to be different:
ruleEqual(comp, res, left.current().getDefaultValue(), right.current().getDefaultValue(), "defaultValue", path);
ruleEqual(comp, res, left.current().getMeaningWhenMissingElement(), right.current().getMeaningWhenMissingElement(), "meaningWhenMissing", path);
@ -256,7 +260,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
matchR.add(r);
StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(l.current(), r.current());
res.getChildren().add(sm);
compareElements(comp, sm, l.path(), null, left, right);
compareElements(comp, sm, l.path(), null, l, r);
}
}
for (DefinitionNavigator r : rc) {
@ -332,7 +336,6 @@ public class ProfileComparer extends CanonicalResourceComparer {
return "left: "+left+"; right: "+right;
}
private List<Coding> mergeCodings(List<Coding> left, List<Coding> right) {
List<Coding> result = new ArrayList<Coding>();
result.addAll(left);
@ -347,7 +350,6 @@ public class ProfileComparer extends CanonicalResourceComparer {
return result;
}
private List<StringType> mergeStrings(List<StringType> left, List<StringType> right) {
List<StringType> result = new ArrayList<StringType>();
result.addAll(left);
@ -434,7 +436,6 @@ public class ProfileComparer extends CanonicalResourceComparer {
return Integer.toString(defn.current().getMin())+".."+defn.current().getMax();
}
private Collection<? extends TypeRefComponent> unionTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
for (TypeRefComponent l : left)
@ -514,14 +515,12 @@ public class ProfileComparer extends CanonicalResourceComparer {
results.add(nw);
}
private boolean derivesFrom(StructureDefinition left, StructureDefinition right) {
// left derives from right if it's base is the same as right
// todo: recursive...
return left.hasBaseDefinition() && left.getBaseDefinition().equals(right.getUrl());
}
private Collection<? extends TypeRefComponent> intersectTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition ed, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
for (TypeRefComponent l : left) {
@ -601,7 +600,6 @@ public class ProfileComparer extends CanonicalResourceComparer {
return b.toString();
}
private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException {
assert(lDef.hasBinding() || rDef.hasBinding());
if (!lDef.hasBinding()) {
@ -746,8 +744,6 @@ public class ProfileComparer extends CanonicalResourceComparer {
return sd;
}
private boolean isPreferredOrExample(ElementDefinitionBindingComponent binding) {
return binding.getStrength() == BindingStrength.EXAMPLE || binding.getStrength() == BindingStrength.PREFERRED;
}

View File

@ -1,33 +1,33 @@
package org.hl7.fhir.r5.context;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

View File

@ -231,6 +231,9 @@ public class DataRenderer {
}
public String display(DataType type) {
if (type.isEmpty())
return "";
if (type instanceof Coding) {
return displayCoding((Coding) type);
} else if (type instanceof CodeableConcept) {
@ -693,7 +696,7 @@ public class DataRenderer {
}
public static String displayPeriod(Period p) {
String s = !p.hasStart() ? "?ngen-5?" : p.getStartElement().toHumanDisplay();
String s = !p.hasStart() ? "(?)" : p.getStartElement().toHumanDisplay();
s = s + " --> ";
return s + (!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay());
}

View File

@ -213,18 +213,26 @@ public class StructureMapUtilities {
return services.resolveReference(appContext, url);
}
private boolean noErrorValidationMessages(List<ValidationMessage> valerrors) {
boolean ok = true;
for (ValidationMessage v : valerrors)
ok = ok && !v.getLevel().isError();
return ok;
}
@Override
public boolean conformsToProfile(Object appContext, Base item, String url) throws FHIRException {
IResourceValidator val = worker.newValidator();
List<ValidationMessage> valerrors = new ArrayList<ValidationMessage>();
if (item instanceof Resource) {
val.validate(appContext, valerrors, (Resource) item, url);
boolean ok = true;
for (ValidationMessage v : valerrors)
ok = ok && v.getLevel().isError();
return ok;
return noErrorValidationMessages(valerrors);
}
throw new NotImplementedException("Not done yet (FFHIRPathHostServices.conformsToProfile), when item is element");
if (item instanceof Element) {
val.validate(appContext, valerrors, (Element) item, url);
return noErrorValidationMessages(valerrors);
}
throw new NotImplementedException("Not done yet (FFHIRPathHostServices.conformsToProfile), when item is not element or not resource");
}
@Override

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -182,7 +182,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
if (!CACHE_VERSION.equals(v)) {
clearCache();
ini.setStringProperty("cache", "version", CACHE_VERSION, null);
save = true;
ini.save();
}
}

View File

@ -99,7 +99,7 @@ Questionnaire_QR_Q_NotFound = The questionnaire "{0}" could not be resolved, so
Questionnaire_Q_EnableWhen_After = The target of this enableWhen rule ({0}) comes after the question itself
Questionnaire_Q_EnableWhen_IsInner = Questions with an enableWhen cannot refer to an inner question for it''s enableWhen condition
Questionnaire_Q_EnableWhen_NoLink = Questions with an enableWhen must have a value for the question link
Questionnaire_Q_EnableWhen_NoTarget = Unable to find target "{0}" for this question enableWhen
Questionnaire_Q_EnableWhen_NoTarget = Unable to find an item with the linkId "{0}" which is referenced in the enableWhen for "{1}"
Questionnaire_Q_EnableWhen_Self = Target for this question enableWhen can''t reference itself
Reference_REF_Aggregation = Reference is {0} which isn''t supported by the specified aggregation mode(s) for the reference
Reference_REF_BadTargetType = Invalid Resource target type. Found {0}, but expected one of ({1})

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.0.6-SNAPSHOT</version>
<version>5.0.7-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.6-SNAPSHOT</version>
<version>5.0.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -95,7 +95,7 @@ public class QuestionnaireValidator extends BaseValidator {
Element tgt = getQuestionById(item, ql);
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt == null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_ISINNER)) {
tgt = getQuestionById(questionnaire, ql);
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOTARGET, ql)) {
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOTARGET, ql, item.getChildValue("linkId"))) {
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != item, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_SELF)) {
if (!isBefore(item, tgt, parents)) {
warning(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_AFTER, ql);

View File

@ -36,8 +36,8 @@ import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.hl7.fhir.validation.instance.InstanceValidatorFactory;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@ -68,14 +68,16 @@ public class FHIRMappingLanguageTests implements ITransformerServices {
@BeforeAll
public static void setUp() throws Exception {
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.1"));
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r5.core", "current"));
if (context.getValidatorFactory() == null) {
context.setValidatorFactory(new InstanceValidatorFactory());
}
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("data")
@Disabled // Test fails: java.lang.AssertionError: Error, but proper output was expected (This does not appear to be a FHIR resource (unknown name "QuestionnaireResponse")
public void test(String name, String source, String map, String output) throws Exception {
InputStream fileSource = TestingUtilities.loadTestResourceStream("r5", "fml", source);

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.6-SNAPSHOT</version>
<version>5.0.7-SNAPSHOT</version>
<properties>
<hapi_fhir_version>5.0.0</hapi_fhir_version>