Merge branch 'master' into tx-server-cache-analysis
This commit is contained in:
commit
0a3e9d3f31
|
@ -304,3 +304,4 @@ local.properties
|
|||
/org.hl7.fhir.r5/src/test/resources/snapshot-generation/logical2-actual.xml
|
||||
/org.hl7.fhir.r5.new
|
||||
/org.hl7.fhir.r5.newc
|
||||
/org.hl7.fhir.r4b.new
|
||||
|
|
|
@ -170,6 +170,7 @@ compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r4', version: '(l
|
|||
compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r5', version: '(latest version)'
|
||||
```
|
||||
|
||||
Note that the built binary validator is released through GitHub releases.
|
||||
### Maintenance
|
||||
This project is maintained by [Grahame Grieve][Link-grahameGithub], [James Agnew][Link-jamesGithub] and [Mark Iantorno][Link-markGithub] on behalf of the FHIR community.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package org.hl7.fhir.convertors.misc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r4b.formats.JsonParser;
|
||||
import org.hl7.fhir.r4b.model.Bundle;
|
||||
import org.hl7.fhir.r4b.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.json.JsonTrackingParser;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.hl7.fhir.r4b.model.SearchParameter;
|
||||
import org.hl7.fhir.r4b.utils.NPMPackageGenerator;
|
||||
import org.hl7.fhir.r4b.utils.NPMPackageGenerator.Category;
|
||||
|
||||
public class ExamplesPackageBuilder {
|
||||
|
||||
public static void main(String[] args) throws FHIRFormatError, FileNotFoundException, IOException {
|
||||
new ExamplesPackageBuilder().process(args[0]);
|
||||
|
||||
}
|
||||
|
||||
private void process(String source) throws FHIRFormatError, FileNotFoundException, IOException {
|
||||
Set<String> set = new HashSet<>();
|
||||
for (File f : new File(source).listFiles()) {
|
||||
if (f.getName().endsWith(".json")) {
|
||||
JsonObject obj = JsonTrackingParser.parseJson(new FileInputStream(f));
|
||||
if (obj.has("resourceType") && obj.has("id")) {
|
||||
String type = obj.get("resourceType").getAsString();
|
||||
String id = obj.get("id").getAsString();
|
||||
byte[] content = TextFile.fileToBytes(f);
|
||||
if (type.equals("ConceptMap")) {
|
||||
System.out.println("convert "+f.getName());
|
||||
content = r5ToR4B(content);
|
||||
TextFile.bytesToFile(content, f);
|
||||
}
|
||||
// TextFile.bytesToFile(content, Utilities.path(dest2, type+"-"+id+".json"));
|
||||
// if (!set.contains(type+"/"+id)) {
|
||||
// set.add(type+"/"+id);
|
||||
// pck.addFile(Category.RESOURCE, type+"-"+id+".json", content);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
// pck.finish();
|
||||
//
|
||||
}
|
||||
|
||||
private byte[] r5ToR4B(byte[] content) throws FHIRFormatError, IOException {
|
||||
try {
|
||||
org.hl7.fhir.r5.model.Resource r5 = new org.hl7.fhir.r5.formats.JsonParser().parse(content);
|
||||
org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(r5);
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(r4);
|
||||
} catch (Exception e) {
|
||||
System.out.println(" .. failed: "+e.getMessage());
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package org.hl7.fhir.core.generator.engine;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r4.formats.JsonParser;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CompartmentDefinition;
|
||||
import org.hl7.fhir.r5.model.ConceptMap;
|
||||
import org.hl7.fhir.r5.model.OperationDefinition;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.utilities.npm.ToolsVersion;
|
||||
|
||||
public class DefinitionsLoaderR4B {
|
||||
|
||||
public static Definitions load(NpmPackage npm) throws IOException {
|
||||
Definitions res = new Definitions();
|
||||
|
||||
for (String t : npm.listResources("CodeSystem")) {
|
||||
res.getCodeSystems().see((CodeSystem) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("ValueSet")) {
|
||||
res.getValuesets().see((ValueSet) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("ConceptMap")) {
|
||||
res.getConceptMaps().see((ConceptMap) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("CapabilityStatement")) {
|
||||
res.getStatements().see((CapabilityStatement) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("StructureDefinition")) {
|
||||
res.getStructures().see((StructureDefinition) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("OperationDefinition")) {
|
||||
res.getOperations().see((OperationDefinition) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("SearchParameter")) {
|
||||
res.getSearchParams().see((SearchParameter) load(npm, t), null);
|
||||
}
|
||||
for (String t : npm.listResources("CompartmentDefinition")) {
|
||||
res.getCompartments().see((CompartmentDefinition) load(npm, t), null);
|
||||
}
|
||||
// Bundle bnd = (Bundle) load(npm, "Bundle-searchParams.json");
|
||||
// if (bnd != null) {
|
||||
// for (BundleEntryComponent be : bnd.getEntry()) {
|
||||
// Resource r = be.getResource();
|
||||
// if (r instanceof CodeSystem) {
|
||||
// res.getCodeSystems().see((CodeSystem) r, null);
|
||||
// } else if (r instanceof ValueSet) {
|
||||
// res.getValuesets().see((ValueSet) r, null);
|
||||
// } else if (r instanceof ConceptMap) {
|
||||
// res.getConceptMaps().see((ConceptMap) r, null);
|
||||
// } else if (r instanceof CapabilityStatement) {
|
||||
// res.getStatements().see((CapabilityStatement) r, null);
|
||||
// } else if (r instanceof StructureDefinition) {
|
||||
// res.getStructures().see((StructureDefinition) r, null);
|
||||
// } else if (r instanceof OperationDefinition) {
|
||||
// res.getOperations().see((OperationDefinition) r, null);
|
||||
// } else if (r instanceof SearchParameter) {
|
||||
// res.getSearchParams().see((SearchParameter) r, null);
|
||||
// } else if (r instanceof CompartmentDefinition) {
|
||||
// res.getCompartments().see((CompartmentDefinition) r, null);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Resource load(NpmPackage npm, String t) {
|
||||
try {
|
||||
return VersionConvertorFactory_40_50.convertResource(new JsonParser().parse(npm.loadResource(t)));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error reading "+t+": "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.hl7.fhir.r4.utils.client.network;
|
||||
|
||||
import okhttp3.*;
|
||||
import okio.Buffer;
|
||||
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -26,8 +28,17 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
public Response intercept(@Nonnull Interceptor.Chain chain) throws IOException {
|
||||
// Log Request
|
||||
Request request = chain.request();
|
||||
logger.logRequest(request.method(), request.url().toString(), new ArrayList<>(request.headers().names()),
|
||||
request.body() != null ? request.body().toString().getBytes() : null);
|
||||
List<String> hdrs = new ArrayList<>();
|
||||
for (String s : request.headers().toString().split("\\n")) {
|
||||
hdrs.add(s.trim());
|
||||
}
|
||||
byte[] cnt = null;
|
||||
if (request.body() != null) {
|
||||
Buffer buf = new Buffer();
|
||||
request.body().writeTo(buf);
|
||||
cnt = buf.readByteArray();
|
||||
}
|
||||
logger.logRequest(request.method(), request.url().toString(), hdrs, cnt);
|
||||
|
||||
// Log Response
|
||||
Response response = null;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.hl7.fhir.r4b.utils.client.network;
|
||||
|
||||
import okhttp3.*;
|
||||
import okio.Buffer;
|
||||
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -26,8 +28,17 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
public Response intercept(@Nonnull Interceptor.Chain chain) throws IOException {
|
||||
// Log Request
|
||||
Request request = chain.request();
|
||||
logger.logRequest(request.method(), request.url().toString(), new ArrayList<>(request.headers().names()),
|
||||
request.body() != null ? request.body().toString().getBytes() : null);
|
||||
List<String> hdrs = new ArrayList<>();
|
||||
for (String s : request.headers().toString().split("\\n")) {
|
||||
hdrs.add(s.trim());
|
||||
}
|
||||
byte[] cnt = null;
|
||||
if (request.body() != null) {
|
||||
Buffer buf = new Buffer();
|
||||
request.body().writeTo(buf);
|
||||
cnt = buf.readByteArray();
|
||||
}
|
||||
logger.logRequest(request.method(), request.url().toString(), hdrs, cnt);
|
||||
|
||||
// Log Response
|
||||
Response response = null;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -45,14 +45,14 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
|
||||
public class ProfileComparison extends CanonicalResourceComparison<StructureDefinition> {
|
||||
|
||||
private StructuralMatch<ElementDefinition> combined;
|
||||
private StructuralMatch<ElementDefinitionNode> combined;
|
||||
|
||||
public ProfileComparison(StructureDefinition left, StructureDefinition right) {
|
||||
super(left, right);
|
||||
combined = new StructuralMatch<ElementDefinition>(); // base
|
||||
combined = new StructuralMatch<ElementDefinitionNode>(); // base
|
||||
}
|
||||
|
||||
public StructuralMatch<ElementDefinition> getCombined() {
|
||||
public StructuralMatch<ElementDefinitionNode> getCombined() {
|
||||
return combined;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,21 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private class ElementDefinitionNode {
|
||||
private ElementDefinition def;
|
||||
private StructureDefinition src;
|
||||
private ElementDefinitionNode(StructureDefinition src, ElementDefinition def) {
|
||||
super();
|
||||
this.src = src;
|
||||
this.def = def;
|
||||
}
|
||||
public ElementDefinition getDef() {
|
||||
return def;
|
||||
}
|
||||
public StructureDefinition getSrc() {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
private ProfileUtilities utilsLeft;
|
||||
private ProfileUtilities utilsRight;
|
||||
|
@ -127,7 +141,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
if (left.getType().equals(right.getType())) {
|
||||
DefinitionNavigator ln = new DefinitionNavigator(session.getContextLeft(), left);
|
||||
DefinitionNavigator rn = new DefinitionNavigator(session.getContextRight(), right);
|
||||
StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(ln.current(), rn.current());
|
||||
StructuralMatch<ElementDefinitionNode> sm = new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(left, ln.current()), new ElementDefinitionNode(right, rn.current()));
|
||||
compareElements(res, sm, ln.path(), null, ln, rn);
|
||||
res.combined = sm;
|
||||
}
|
||||
|
@ -147,7 +161,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
throw new DefinitionException("StructureDefinition snapshot is empty ("+name+": "+sd.getName()+")");
|
||||
}
|
||||
|
||||
private void compareElements(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, String sliceName, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, FHIRFormatError, IOException {
|
||||
private void compareElements(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String sliceName, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, FHIRFormatError, IOException {
|
||||
assert(path != null);
|
||||
assert(left != null);
|
||||
assert(right != null);
|
||||
|
@ -190,7 +204,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
subset.setExample(left.current().hasExample() ? left.current().getExample() : right.current().getExample());
|
||||
|
||||
if (left.current().getMustSupport() != right.current().getMustSupport()) {
|
||||
vm(IssueSeverity.ERROR, "Elements differ in definition for mustSupport:\r\n \""+left.current().getMustSupport()+"\"\r\n \""+right.current().getMustSupport()+"\"", path, comp.getMessages(), res.getMessages());
|
||||
vm(IssueSeverity.WARNING, "Elements differ in definition for mustSupport: '"+left.current().getMustSupport()+"' vs '"+right.current().getMustSupport()+"'", path, comp.getMessages(), res.getMessages());
|
||||
|
||||
}
|
||||
subset.setMustSupport(left.current().getMustSupport() || right.current().getMustSupport());
|
||||
|
@ -198,15 +212,20 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
|
||||
|
||||
// compare and intersect
|
||||
superset.setMin(unionMin(left.current().getMin(), right.current().getMin()));
|
||||
superset.setMax(unionMax(left.current().getMax(), right.current().getMax()));
|
||||
subset.setMin(intersectMin(left.current().getMin(), right.current().getMin()));
|
||||
subset.setMax(intersectMax(left.current().getMax(), right.current().getMax()));
|
||||
rule(comp, res, subset.getMax().equals("*") || Integer.parseInt(subset.getMax()) >= subset.getMin(), path, "Cardinality Mismatch: "+card(left)+"/"+card(right));
|
||||
int leftMin = left.current().getMin();
|
||||
int rightMin = right.current().getMin();
|
||||
int leftMax = "*".equals(left.current().getMax()) ? Integer.MAX_VALUE : Integer.parseInt(left.current().getMax());
|
||||
int rightMax = "*".equals(right.current().getMax()) ? Integer.MAX_VALUE : Integer.parseInt(right.current().getMax());
|
||||
|
||||
checkMinMax(comp, res, path, leftMin, rightMin, leftMax, rightMax);
|
||||
superset.setMin(unionMin(leftMin, rightMin));
|
||||
superset.setMax(unionMax(leftMax, rightMax, left.current().getMax(), right.current().getMax()));
|
||||
subset.setMin(intersectMin(leftMin, rightMin));
|
||||
subset.setMax(intersectMax(leftMax, rightMax, left.current().getMax(), right.current().getMax()));
|
||||
|
||||
superset.getType().addAll(unionTypes(comp, res, path, left.current().getType(), right.current().getType()));
|
||||
subset.getType().addAll(intersectTypes(comp, res, subset, path, left.current().getType(), right.current().getType()));
|
||||
rule(comp, res, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch:\r\n "+typeCode(left)+"\r\n "+typeCode(right));
|
||||
rule(comp, res, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch: "+typeCode(left)+" vs "+typeCode(right));
|
||||
// <fixed[x]><!-- ?? 0..1 * Value must be exactly this --></fixed[x]>
|
||||
// <pattern[x]><!-- ?? 0..1 * Value must have at least these property values --></pattern[x]>
|
||||
superset.setMaxLengthElement(unionMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
|
||||
|
@ -283,7 +302,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
// return null;
|
||||
}
|
||||
|
||||
private void compareChildren(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException, FHIRFormatError {
|
||||
|
||||
private void compareChildren(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException, FHIRFormatError {
|
||||
List<DefinitionNavigator> lc = left.children();
|
||||
List<DefinitionNavigator> rc = right.children();
|
||||
// it's possible that one of these profiles walks into a data type and the other doesn't
|
||||
|
@ -299,10 +319,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
DefinitionNavigator r = findInList(rc, l);
|
||||
if (r == null) {
|
||||
comp.getUnion().getSnapshot().getElement().add(l.current().copy());
|
||||
res.getChildren().add(new StructuralMatch<ElementDefinition>(l.current(), vmI(IssueSeverity.INFORMATION, "Removed this element", path)));
|
||||
res.getChildren().add(new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(l.getStructure(), l.current()), vmI(IssueSeverity.INFORMATION, "Removed this element", path)));
|
||||
} else {
|
||||
matchR.add(r);
|
||||
StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(l.current(), r.current());
|
||||
StructuralMatch<ElementDefinitionNode> sm = new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(l.getStructure(), l.current()), new ElementDefinitionNode(r.getStructure(), r.current()));
|
||||
res.getChildren().add(sm);
|
||||
compareElements(comp, sm, l.path(), null, l, r);
|
||||
}
|
||||
|
@ -310,7 +330,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
for (DefinitionNavigator r : rc) {
|
||||
if (!matchR.contains(r)) {
|
||||
comp.getUnion().getSnapshot().getElement().add(r.current().copy());
|
||||
res.getChildren().add(new StructuralMatch<ElementDefinition>(vmI(IssueSeverity.INFORMATION, "Added this element", path), r.current()));
|
||||
res.getChildren().add(new StructuralMatch<ElementDefinitionNode>(vmI(IssueSeverity.INFORMATION, "Added this element", path), new ElementDefinitionNode(r.getStructure(), r.current())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +344,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void ruleEqual(ProfileComparison comp, StructuralMatch<ElementDefinition> res, DataType vLeft, DataType vRight, String name, String path) throws IOException {
|
||||
private void ruleEqual(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, DataType vLeft, DataType vRight, String name, String path) throws IOException {
|
||||
if (vLeft == null && vRight == null) {
|
||||
// nothing
|
||||
} else if (vLeft == null) {
|
||||
|
@ -338,7 +358,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
|
||||
private String toString(DataType val, boolean left) throws IOException {
|
||||
if (val instanceof PrimitiveType)
|
||||
return "\"" + ((PrimitiveType) val).getValueAsString()+"\"";
|
||||
return "'" + ((PrimitiveType) val).getValueAsString()+"'";
|
||||
|
||||
IParser jp = left ? session.getContextLeft().newJsonParser() : session.getContextRight().newJsonParser();
|
||||
return jp.composeString(val, "value");
|
||||
|
@ -356,14 +376,14 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return s;
|
||||
}
|
||||
|
||||
private boolean rule(ProfileComparison comp, StructuralMatch<ElementDefinition> res, boolean test, String path, String message) {
|
||||
private boolean rule(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, boolean test, String path, String message) {
|
||||
if (!test) {
|
||||
vm(IssueSeverity.ERROR, message, path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
private String mergeText(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, String name, String left, String right, boolean isError) {
|
||||
private String mergeText(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String name, String left, String right, boolean isError) {
|
||||
if (left == null && right == null)
|
||||
return null;
|
||||
if (left == null)
|
||||
|
@ -375,7 +395,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
if (left.equalsIgnoreCase(right))
|
||||
return left;
|
||||
if (path != null) {
|
||||
vm(isError ? IssueSeverity.ERROR : IssueSeverity.WARNING, "Elements differ in "+name+":\r\n \""+left+"\"\r\n \""+right+"\"", path, comp.getMessages(), res.getMessages());
|
||||
vm(isError ? IssueSeverity.ERROR : IssueSeverity.WARNING, "Elements differ in "+name+": '"+left+"' vs '"+right+"'", path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
return "left: "+left+"; right: "+right;
|
||||
}
|
||||
|
@ -429,6 +449,36 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return right;
|
||||
}
|
||||
|
||||
private void checkMinMax(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, int leftMin, int rightMin, int leftMax, int rightMax) {
|
||||
if (leftMin != rightMin) {
|
||||
if (leftMin == 0) {
|
||||
vm(IssueSeverity.INFORMATION, "Element minimum cardinalities differ: '"+leftMin+"' vs '"+rightMin+"'", path, comp.getMessages(), res.getMessages());
|
||||
} else if (rightMin == 0) {
|
||||
vm(IssueSeverity.INFORMATION, "Element minimum cardinalities differ: '"+leftMin+"' vs '"+rightMin+"'", path, comp.getMessages(), res.getMessages());
|
||||
} else {
|
||||
vm(IssueSeverity.INFORMATION, "Element minimum cardinalities differ: '"+leftMin+"' vs '"+rightMin+"'", path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
}
|
||||
if (leftMax != rightMax) {
|
||||
if (leftMax == Integer.MAX_VALUE) {
|
||||
vm(IssueSeverity.INFORMATION, "Element maximum cardinalities differ: '"+leftMax+"' vs '"+rightMax+"'", path, comp.getMessages(), res.getMessages());
|
||||
} else if (rightMax == Integer.MAX_VALUE) {
|
||||
vm(IssueSeverity.INFORMATION, "Element maximum cardinalities differ: '"+leftMax+"' vs '"+rightMax+"'", path, comp.getMessages(), res.getMessages());
|
||||
} else {
|
||||
vm(IssueSeverity.INFORMATION, "Element maximum cardinalities differ: '"+leftMax+"' vs '"+rightMax+"'", path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
}
|
||||
// rule(comp, res, subset.getMax().equals("*") || Integer.parseInt(subset.getMax()) >= subset.getMin(), path, "Cardinality Mismatch: "+card(left)+"/"+card(right));
|
||||
|
||||
// cross comparison - if max > min in either direction, there can be no instances that are valid against both
|
||||
if (leftMax < rightMin) {
|
||||
vm(IssueSeverity.ERROR, "Element minimum cardinalities conflict: '"+leftMin+".."+leftMax+"' vs '"+rightMin+".."+rightMax+"': No instances can be valid against both profiles", path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
if (rightMax < leftMin) {
|
||||
vm(IssueSeverity.ERROR, "Element minimum cardinalities conflict: '"+leftMin+".."+leftMax+"' vs '"+rightMin+".."+rightMax+"': No instances can be valid against both profiles", path, comp.getMessages(), res.getMessages());
|
||||
}
|
||||
}
|
||||
|
||||
private int unionMin(int left, int right) {
|
||||
if (left > right)
|
||||
return right;
|
||||
|
@ -436,18 +486,14 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return left;
|
||||
}
|
||||
|
||||
private String intersectMax(String left, String right) {
|
||||
int l = "*".equals(left) ? Integer.MAX_VALUE : Integer.parseInt(left);
|
||||
int r = "*".equals(right) ? Integer.MAX_VALUE : Integer.parseInt(right);
|
||||
private String intersectMax(int l, int r, String left, String right) {
|
||||
if (l < r)
|
||||
return left;
|
||||
else
|
||||
return right;
|
||||
}
|
||||
|
||||
private String unionMax(String left, String right) {
|
||||
int l = "*".equals(left) ? Integer.MAX_VALUE : Integer.parseInt(left);
|
||||
int r = "*".equals(right) ? Integer.MAX_VALUE : Integer.parseInt(right);
|
||||
private String unionMax(int l, int r, String left, String right) {
|
||||
if (l < r)
|
||||
return right;
|
||||
else
|
||||
|
@ -480,7 +526,7 @@ 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 {
|
||||
private Collection<? extends TypeRefComponent> unionTypes(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
|
||||
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
|
||||
for (TypeRefComponent l : left)
|
||||
checkAddTypeUnion(comp, res, path, result, l, session.getContextLeft());
|
||||
|
@ -489,7 +535,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return result;
|
||||
}
|
||||
|
||||
private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<TypeRefComponent> results, TypeRefComponent nw, IWorkerContext ctxt) throws DefinitionException, IOException, FHIRFormatError {
|
||||
private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> results, TypeRefComponent nw, IWorkerContext ctxt) throws DefinitionException, IOException, FHIRFormatError {
|
||||
boolean pfound = false;
|
||||
boolean tfound = false;
|
||||
nw = nw.copy();
|
||||
|
@ -586,7 +632,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return false;
|
||||
}
|
||||
|
||||
private Collection<? extends TypeRefComponent> intersectTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition ed, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
|
||||
private Collection<? extends TypeRefComponent> intersectTypes(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> 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) {
|
||||
if (l.hasAggregation())
|
||||
|
@ -665,7 +711,7 @@ 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 {
|
||||
private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException {
|
||||
assert(lDef.hasBinding() || rDef.hasBinding());
|
||||
if (!lDef.hasBinding()) {
|
||||
subset.setBinding(rDef.getBinding());
|
||||
|
@ -801,7 +847,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
}
|
||||
|
||||
// we can't really know about constraints. We create warnings, and collate them
|
||||
private List<ElementDefinitionConstraintComponent> unionConstraints(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<ElementDefinitionConstraintComponent> left, List<ElementDefinitionConstraintComponent> right) {
|
||||
private List<ElementDefinitionConstraintComponent> unionConstraints(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<ElementDefinitionConstraintComponent> left, List<ElementDefinitionConstraintComponent> right) {
|
||||
List<ElementDefinitionConstraintComponent> result = new ArrayList<ElementDefinitionConstraintComponent>();
|
||||
for (ElementDefinitionConstraintComponent l : left) {
|
||||
boolean found = false;
|
||||
|
@ -829,7 +875,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return result;
|
||||
}
|
||||
|
||||
private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, String url, String name, IWorkerContext ctxt) {
|
||||
private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String url, String name, IWorkerContext ctxt) {
|
||||
StructureDefinition sd = ctxt.fetchResource(StructureDefinition.class, url);
|
||||
if (sd == null) {
|
||||
ValidationMessage vm = vmI(IssueSeverity.WARNING, "Unable to resolve profile "+url+" in profile "+name, path);
|
||||
|
@ -841,7 +887,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return binding.getStrength() == BindingStrength.EXAMPLE || binding.getStrength() == BindingStrength.PREFERRED;
|
||||
}
|
||||
|
||||
private ElementDefinitionBindingComponent unionBindings(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right) throws FHIRFormatError, DefinitionException, IOException {
|
||||
private ElementDefinitionBindingComponent unionBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right) throws FHIRFormatError, DefinitionException, IOException {
|
||||
ElementDefinitionBindingComponent union = new ElementDefinitionBindingComponent();
|
||||
if (left.getStrength().compareTo(right.getStrength()) < 0)
|
||||
union.setStrength(left.getStrength());
|
||||
|
@ -881,17 +927,17 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return gen.generate(model, prefix, 0, null);
|
||||
}
|
||||
|
||||
private void genElementComp(String defPath, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinition> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
|
||||
private void genElementComp(String defPath, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinitionNode> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
|
||||
Row originalRow = slicingRow;
|
||||
Row typesRow = null;
|
||||
|
||||
List<StructuralMatch<ElementDefinition>> children = combined.getChildren();
|
||||
List<StructuralMatch<ElementDefinitionNode>> children = combined.getChildren();
|
||||
|
||||
Row row = gen.new Row();
|
||||
rows.add(row);
|
||||
String path = combined.either().getPath();
|
||||
String path = combined.either().getDef().getPath();
|
||||
row.setAnchor(path);
|
||||
row.setColor(utilsRight.getRowColor(combined.either(), false));
|
||||
row.setColor(utilsRight.getRowColor(combined.either().getDef(), false));
|
||||
if (eitherHasSlicing(combined))
|
||||
row.setLineColor(1);
|
||||
else if (eitherHasSliceName(combined))
|
||||
|
@ -917,7 +963,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE);
|
||||
typesRow = row;
|
||||
}
|
||||
} else if (combined.either().hasContentReference())
|
||||
} else if (combined.either().getDef().hasContentReference())
|
||||
row.setIcon("icon_reuse.png", HierarchicalTableGenerator.TEXT_ICON_REUSE);
|
||||
else if (isPrimitive(combined))
|
||||
row.setIcon("icon_primitive.png", HierarchicalTableGenerator.TEXT_ICON_PRIMITIVE);
|
||||
|
@ -927,7 +973,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
row.setIcon("icon_datatype.gif", HierarchicalTableGenerator.TEXT_ICON_DATATYPE);
|
||||
else
|
||||
row.setIcon("icon_resource.png", HierarchicalTableGenerator.TEXT_ICON_RESOURCE);
|
||||
String ref = defPath == null ? null : defPath + combined.either().getId();
|
||||
String ref = defPath == null ? null : defPath + combined.either().getDef().getId();
|
||||
String sName = tail(path);
|
||||
String sn = getSliceName(combined);
|
||||
if (sn != null)
|
||||
|
@ -937,23 +983,23 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
String leftColor = !combined.hasLeft() ? COLOR_NO_ROW_LEFT : combined.hasErrors() ? COLOR_DIFFERENT : null;
|
||||
String rightColor = !combined.hasRight() ? COLOR_NO_ROW_LEFT : combined.hasErrors() ? COLOR_DIFFERENT : null;
|
||||
if (combined.hasLeft()) {
|
||||
nc = utilsRight.genElementNameCell(gen, combined.getLeft(), "??", true, corePath, prefix, root, false, false, null, typesRow, row, false, ext, used , ref, sName);
|
||||
nc = utilsRight.genElementNameCell(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, false, ext, used , ref, sName);
|
||||
} else {
|
||||
nc = utilsRight.genElementNameCell(gen, combined.getRight(), "??", true, corePath, prefix, root, false, false, null, typesRow, row, false, ext, used , ref, sName);
|
||||
nc = utilsRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName);
|
||||
}
|
||||
if (combined.hasLeft()) {
|
||||
frame(utilsRight.genElementCells(gen, combined.getLeft(), "??", true, corePath, prefix, root, false, false, null, typesRow, row, false, ext, used , ref, sName, nc, false), leftColor);
|
||||
frame(utilsRight.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false), leftColor);
|
||||
} else {
|
||||
frame(spacers(row, 4, gen), leftColor);
|
||||
}
|
||||
if (combined.hasRight()) {
|
||||
frame(utilsRight.genElementCells(gen, combined.getRight(), "??", true, corePath, prefix, root, false, false, null, typesRow, row, false, ext, used, ref, sName, nc, false), rightColor);
|
||||
frame(utilsRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false), rightColor);
|
||||
} else {
|
||||
frame(spacers(row, 4, gen), rightColor);
|
||||
}
|
||||
row.getCells().add(cellForMessages(gen, combined.getMessages()));
|
||||
|
||||
for (StructuralMatch<ElementDefinition> child : children) {
|
||||
for (StructuralMatch<ElementDefinitionNode> child : children) {
|
||||
genElementComp(defPath, gen, row.getSubRows(), child, corePath, prefix, originalRow, false);
|
||||
}
|
||||
}
|
||||
|
@ -978,47 +1024,47 @@ public class ProfileComparer extends CanonicalResourceComparer {
|
|||
return res;
|
||||
}
|
||||
|
||||
private String getSliceName(StructuralMatch<ElementDefinition> combined) {
|
||||
private String getSliceName(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isDataType(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean isDataType(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasTarget(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean hasTarget(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPrimitive(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean isPrimitive(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean allAreReference(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean allAreReference(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasChoice(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean hasChoice(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean elementIsComplex(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean elementIsComplex(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub velement.hasType() && element.getType().get(0).hasProfile() && extensionIsComplex(element.getType().get(0).getProfile().get(0).getValue()
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean eitherHasSliceName(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean eitherHasSliceName(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean eitherHasSlicing(StructuralMatch<ElementDefinition> combined) {
|
||||
private boolean eitherHasSlicing(StructuralMatch<ElementDefinitionNode> combined) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -301,11 +301,11 @@ public class ResourceComparer {
|
|||
private String halfColorForLevel(IssueSeverity level) {
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
return "#ffeeee";
|
||||
return "#ffdddd";
|
||||
case FATAL:
|
||||
return "#ffcccc";
|
||||
case WARNING:
|
||||
return "#fff4ee";
|
||||
return "#fff6ee";
|
||||
default: // INFORMATION:
|
||||
return "#fffff2";
|
||||
}
|
||||
|
@ -319,6 +319,9 @@ public class ResourceComparer {
|
|||
XhtmlNode li = new XhtmlNode(NodeType.Element, "li");
|
||||
piece.getChildren().add(li);
|
||||
li.style("background-color: "+halfColorForLevel(msg.getLevel()));
|
||||
if (msg.getLevel() == IssueSeverity.ERROR) {
|
||||
li.style("font-weight: bold");
|
||||
}
|
||||
li.tx(msg.getMessage());
|
||||
}
|
||||
return cell;
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.comparison.ResourceComparer.MessageCounts;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
||||
|
@ -113,5 +114,6 @@ public class StructuralMatch<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -36,6 +36,9 @@ import java.io.FileReader;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -3504,7 +3507,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
List<TypeRefComponent> types = e.getType();
|
||||
if (!e.hasType()) {
|
||||
if (root) { // we'll use base instead of types then
|
||||
StructureDefinition bsd = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition());
|
||||
StructureDefinition bsd = profile == null ? null : context.fetchResource(StructureDefinition.class, profile.getBaseDefinition());
|
||||
if (bsd != null) {
|
||||
if (bsd.hasUserData("path")) {
|
||||
c.getPieces().add(gen.new Piece(Utilities.isAbsoluteUrl(bsd.getUserString("path")) ? bsd.getUserString("path") : imagePath +bsd.getUserString("path"), bsd.getName(), null));
|
||||
|
@ -3586,7 +3589,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.addPiece(checkForNoChange(tl, gen.new Piece(null,", ", null)));
|
||||
}
|
||||
|
||||
ref = pkp.getLinkForProfile(profile, p.getValue());
|
||||
ref = pkp == null ? null : pkp.getLinkForProfile(profile, p.getValue());
|
||||
if (ref != null) {
|
||||
String[] parts = ref.split("\\|");
|
||||
if (parts[0].startsWith("http:") || parts[0].startsWith("https:")) {
|
||||
|
@ -3685,7 +3688,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
|
||||
private String checkPrepend(String corePath, String path) {
|
||||
if (pkp.prependLinks() && !(path.startsWith("http:") || path.startsWith("https:")))
|
||||
if (pkp != null && pkp.prependLinks() && !(path.startsWith("http:") || path.startsWith("https:")))
|
||||
return corePath+path;
|
||||
else
|
||||
return path;
|
||||
|
@ -4057,7 +4060,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (logicalModel && element.hasRepresentation(PropertyRepresentation.XMLATTR))
|
||||
sName = "@"+sName;
|
||||
Cell nc = genElementNameCell(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName);
|
||||
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport);
|
||||
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true);
|
||||
if (element.hasSlicing()) {
|
||||
if (standardExtensionSlicing(element)) {
|
||||
used.used = true; // doesn't matter whether we have a type, we're used if we're setting up slicing ... element.hasType() && element.getType().get(0).hasProfile();
|
||||
|
@ -4185,7 +4188,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
public List<Cell> genElementCells(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath,
|
||||
String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef,
|
||||
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport) throws IOException {
|
||||
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows) throws IOException {
|
||||
List<Cell> res = new ArrayList<>();
|
||||
Cell gc = gen.new Cell();
|
||||
row.getCells().add(gc);
|
||||
|
@ -4211,7 +4214,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (extDefn == null) {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
res.add(addCell(row, gen.new Cell(null, null, "?gen-e1? "+element.getType().get(0).getProfile(), null, null)));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows));
|
||||
} else {
|
||||
String name = urltail(eurl);
|
||||
nameCell.getPieces().get(0).setText(name);
|
||||
|
@ -4224,7 +4227,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
else // if it's complex, we just call it nothing
|
||||
// genTypes(gen, row, extDefn.getSnapshot().getElement().get(0), profileBaseFileName, profile);
|
||||
res.add(addCell(row, gen.new Cell(null, null, "("+translate("sd.table", "Complex")+")", null, null)));
|
||||
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows));
|
||||
}
|
||||
} else {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
|
@ -4232,7 +4235,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
res.add(addCell(row, gen.new Cell()));
|
||||
else
|
||||
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows));
|
||||
}
|
||||
} else {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
|
@ -4240,7 +4243,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
|
||||
else
|
||||
res.add(addCell(row, gen.new Cell()));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -4546,11 +4549,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
&& element.getSlicing().getRules() != SlicingRules.CLOSED && element.getSlicing().getDiscriminator().size() == 1 && element.getSlicing().getDiscriminator().get(0).getPath().equals("url") && element.getSlicing().getDiscriminator().get(0).getType().equals(DiscriminatorType.VALUE);
|
||||
}
|
||||
|
||||
private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly) throws IOException, FHIRException {
|
||||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly);
|
||||
private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows) throws IOException, FHIRException {
|
||||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows);
|
||||
}
|
||||
|
||||
private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly) throws IOException, FHIRException {
|
||||
private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows) throws IOException, FHIRException {
|
||||
Cell c = gen.new Cell();
|
||||
row.getCells().add(c);
|
||||
|
||||
|
@ -4566,7 +4569,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
if (root) {
|
||||
if (profile.getAbstract()) {
|
||||
if (profile != null && profile.getAbstract()) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.addPiece(gen.new Piece(null, "This is an abstract profile", null));
|
||||
}
|
||||
|
@ -4661,7 +4664,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (binding!=null && !binding.isEmpty()) {
|
||||
if (!c.getPieces().isEmpty())
|
||||
c.addPiece(gen.new Piece("br"));
|
||||
BindingResolution br = pkp.resolveBinding(profile, binding, definition.getPath());
|
||||
BindingResolution br = pkp == null ? makeNullBr(binding) : pkp.resolveBinding(profile, binding, definition.getPath());
|
||||
c.getPieces().add(checkForNoChange(binding, gen.new Piece(null, translate("sd.table", "Binding")+": ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(binding.getValueSetElement(), gen.new Piece(br.url == null ? null : Utilities.isAbsoluteUrl(br.url) || !pkp.prependLinks() ? br.url : corePath+br.url, br.display, null)));
|
||||
if (binding.hasStrength()) {
|
||||
|
@ -4670,7 +4673,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(checkForNoChange(binding.getStrengthElement(), gen.new Piece(null, ")", null)));
|
||||
}
|
||||
if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET)) {
|
||||
br = pkp.resolveBinding(profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), definition.getPath());
|
||||
br = pkp == null ? makeNullBr(binding) : pkp.resolveBinding(profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), definition.getPath());
|
||||
c.addPiece(gen.new Piece("br"));
|
||||
c.getPieces().add(checkForNoChange(binding, gen.new Piece(corePath+"extension-elementdefinition-maxvalueset.html", translate("sd.table", "Max Binding")+": ", "Max Value Set Extension").addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(binding, gen.new Piece(br.url == null ? null : Utilities.isAbsoluteUrl(br.url) || !pkp.prependLinks() ? br.url : corePath+br.url, br.display, null)));
|
||||
|
@ -4706,7 +4709,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (definition.hasFixed()) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, translate("sd.table", "Fixed Value")+": ", null).addStyle("font-weight:bold")));
|
||||
if (!useTableForFixedValues || definition.getFixed().isPrimitive()) {
|
||||
if (!useTableForFixedValues || !allowSubRows || definition.getFixed().isPrimitive()) {
|
||||
String s = buildJson(definition.getFixed());
|
||||
String link = null;
|
||||
if (Utilities.isAbsoluteUrl(s))
|
||||
|
@ -4714,7 +4717,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(link, s, null).addStyle("color: darkgreen")));
|
||||
} else {
|
||||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "As shown", null).addStyle("color: darkgreen")));
|
||||
genFixedValue(gen, row, definition.getFixed(), snapshot, false, corePath, false);
|
||||
genFixedValue(gen, row, definition.getFixed(), snapshot, false, corePath, false);
|
||||
}
|
||||
if (isCoded(definition.getFixed()) && !hasDescription(definition.getFixed())) {
|
||||
Piece p = describeCoded(gen, definition.getFixed());
|
||||
|
@ -4724,7 +4727,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
} else if (definition.hasPattern()) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, translate("sd.table", "Required Pattern")+": ", null).addStyle("font-weight:bold")));
|
||||
if (!useTableForFixedValues || definition.getPattern().isPrimitive())
|
||||
if (!useTableForFixedValues || !allowSubRows || definition.getPattern().isPrimitive())
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
|
||||
else {
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, "At least the following", null).addStyle("color: darkgreen")));
|
||||
|
@ -4764,6 +4767,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
return c;
|
||||
}
|
||||
|
||||
private BindingResolution makeNullBr(ElementDefinitionBindingComponent binding) {
|
||||
BindingResolution br = new BindingResolution();
|
||||
br.url = "http://none.none/none";
|
||||
br.display = "todo";
|
||||
return br;
|
||||
}
|
||||
|
||||
private ElementDefinitionBindingComponent makeUnifiedBinding(ElementDefinitionBindingComponent binding, ElementDefinition element) {
|
||||
if (!element.hasUserData(DERIVATION_POINTER)) {
|
||||
return binding;
|
||||
|
@ -4804,7 +4814,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
ref = "?gen-fv?";
|
||||
}
|
||||
StructureDefinition sd = context.fetchTypeDefinition(value.fhirType());
|
||||
|
||||
|
||||
for (org.hl7.fhir.r5.model.Property t : value.children()) {
|
||||
if (t.getValues().size() > 0 || snapshot) {
|
||||
ElementDefinition ed = findElementDefinition(sd, t.getName());
|
||||
|
|
|
@ -1156,7 +1156,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem());
|
||||
if (cs != null) {
|
||||
if (cs != null && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
|
||||
pin.addParameter().setName("tx-resource").setResource(cs);
|
||||
if (isTxCaching && cacheId == null || !cached.contains(cs.getVUrl())) {
|
||||
cached.add(cs.getVUrl());
|
||||
|
|
|
@ -3,34 +3,34 @@ package org.hl7.fhir.r5.formats;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -63,6 +63,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URI;
|
||||
|
||||
|
@ -117,25 +118,31 @@ public abstract class FormatUtilities {
|
|||
}
|
||||
|
||||
public static ParserBase makeParser(FhirFormat format) {
|
||||
switch (format) {
|
||||
case XML : return new XmlParser();
|
||||
case JSON : return new JsonParser();
|
||||
case TURTLE : throw new Error("unsupported Format "+format.toString()); // return new TurtleParser();
|
||||
case VBAR : throw new Error("unsupported Format "+format.toString()); //
|
||||
case TEXT : throw new Error("unsupported Format "+format.toString()); //
|
||||
}
|
||||
throw new Error("unsupported Format "+format.toString());
|
||||
return makeParser(format.name());
|
||||
}
|
||||
|
||||
public static ParserBase makeParser(String format) {
|
||||
if ("XML".equalsIgnoreCase(format)) return new XmlParser();
|
||||
if ("JSON".equalsIgnoreCase(format)) return new JsonParser();
|
||||
if ("TURTLE".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // return new TurtleParser();
|
||||
if ("JSONLD".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // return new JsonLdParser();
|
||||
if ("VBAR".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); //
|
||||
if ("TEXT".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); //
|
||||
throw new Error("unsupported Format "+format);
|
||||
}
|
||||
/*
|
||||
* Note: Use fully qualified references to the parsers here in order to avoid adding
|
||||
* a class-level import statement for them. This is because the
|
||||
* XmlParser and JsonParser are huuuuuge classes and classloading them is quite expensive
|
||||
* in cases where they won't actually ever be instantiated (such as when using the
|
||||
* validator in HAPI FHIR).
|
||||
*
|
||||
* See https://github.com/hapifhir/hapi-fhir/issues/3268
|
||||
*/
|
||||
if ("XML".equalsIgnoreCase(format))
|
||||
return new org.hl7.fhir.r5.formats.XmlParser();
|
||||
if ("JSON".equalsIgnoreCase(format))
|
||||
return new org.hl7.fhir.r5.formats.JsonParser();
|
||||
if ("TURTLE".equalsIgnoreCase(format))
|
||||
throw new Error("unsupported Format " + format.toString()); // return new TurtleParser();
|
||||
if ("JSONLD".equalsIgnoreCase(format))
|
||||
throw new Error("unsupported Format " + format.toString()); // return new JsonLdParser();
|
||||
if ("VBAR".equalsIgnoreCase(format)) throw new Error("unsupported Format " + format.toString()); //
|
||||
if ("TEXT".equalsIgnoreCase(format)) throw new Error("unsupported Format " + format.toString()); //
|
||||
throw new Error("unsupported Format " + format);
|
||||
}
|
||||
|
||||
public static FhirFormat determineFormat(byte[] source) throws FHIRException {
|
||||
return determineFormat(source, MAX_SCAN_LENGTH);
|
||||
|
|
|
@ -614,6 +614,9 @@ public class ExpressionNode {
|
|||
|
||||
public String check() {
|
||||
|
||||
if (kind == null) {
|
||||
return "Error in expression - node has no kind";
|
||||
}
|
||||
switch (kind) {
|
||||
case Name:
|
||||
if (Utilities.noString(name))
|
||||
|
|
|
@ -175,7 +175,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
hierarchy = hierarchy || csNav.isRestructure();
|
||||
|
||||
List<String> langs = new ArrayList<>();
|
||||
addMapHeaders(addTableHeaderRowStandard(t, hierarchy, display, definitions, commentS, version, deprecated, properties, null, false), maps);
|
||||
addMapHeaders(addTableHeaderRowStandard(t, hierarchy, display, definitions, commentS, version, deprecated, properties, null, null, false), maps);
|
||||
for (ConceptDefinitionComponent c : csNav.getConcepts(null)) {
|
||||
hasExtensions = addDefineRowToTable(t, c, 0, hierarchy, display, definitions, commentS, version, deprecated, maps, cs.getUrl(), cs, properties, csNav, langs, isSupplement) || hasExtensions;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hl7.fhir.r5.model.Narrative;
|
|||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
|
@ -488,4 +489,16 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
private String getPrimitiveValue(ResourceWrapper r, String name) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
return r.has(name) && r.getChildByName(name).hasValues() ? r.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null;
|
||||
}
|
||||
|
||||
public void renderOrError(DomainResource dr) {
|
||||
try {
|
||||
render(dr);
|
||||
} catch (Exception e) {
|
||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||
x.para().tx("Error rendering: "+e.getMessage());
|
||||
dr.setText(null);
|
||||
inject(dr, x, NarrativeStatus.GENERATED);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
|
@ -201,7 +202,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected XhtmlNode addTableHeaderRowStandard(XhtmlNode t, boolean hasHierarchy, boolean hasDisplay, boolean definitions, boolean comments, boolean version, boolean deprecated, List<PropertyComponent> properties, List<String> langs, boolean doLangs) {
|
||||
protected XhtmlNode addTableHeaderRowStandard(XhtmlNode t, boolean hasHierarchy, boolean hasDisplay, boolean definitions, boolean comments, boolean version, boolean deprecated, List<PropertyComponent> properties, List<String> langs, Map<String, String> designations, boolean doDesignations) {
|
||||
XhtmlNode tr = t.tr();
|
||||
if (hasHierarchy) {
|
||||
tr.td().b().tx("Lvl");
|
||||
|
@ -234,7 +235,10 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
|
|||
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", display, getContext().getLang()));
|
||||
}
|
||||
}
|
||||
if (doLangs) {
|
||||
if (doDesignations) {
|
||||
for (String url : designations.keySet()) {
|
||||
tr.td().b().addText(designations.get(url));
|
||||
}
|
||||
for (String lang : langs) {
|
||||
tr.td().b().addText(describeLang(lang));
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hl7.fhir.r5.model.ConceptMap;
|
|||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.ExtensionHelper;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
|
@ -39,6 +40,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||
|
@ -48,7 +50,11 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
|||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Title;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
@ -65,7 +71,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
|
||||
private static final String ABSTRACT_CODE_HINT = "This code is not selectable ('Abstract')";
|
||||
|
||||
private static final int MAX_LANGS_IN_LINE = 5;
|
||||
private static final int MAX_DESIGNATIONS_IN_LINE = 5;
|
||||
|
||||
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
|
||||
|
||||
|
@ -222,7 +228,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
doLangs = false;
|
||||
} else {
|
||||
// if we're not doing definitions and we don't have too many languages, we'll do them in line
|
||||
if (langs.size() < MAX_LANGS_IN_LINE) {
|
||||
if (langs.size() < MAX_DESIGNATIONS_IN_LINE) {
|
||||
doLangs = true;
|
||||
if (vs.hasLanguage()) {
|
||||
tdDisp.tx(" - "+describeLang(vs.getLanguage()));
|
||||
|
@ -586,8 +592,12 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
private boolean checkDoDefinition(List<ValueSetExpansionContainsComponent> contains) {
|
||||
for (ValueSetExpansionContainsComponent c : contains) {
|
||||
CodeSystem cs = getContext().getWorker().fetchCodeSystem(c.getSystem());
|
||||
if (cs != null)
|
||||
return true;
|
||||
if (cs != null) {
|
||||
ConceptDefinitionComponent cd = CodeSystemUtilities.getCode(cs, c.getCode());
|
||||
if (cd != null && cd.hasDefinition()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (checkDoDefinition(c.getContains()))
|
||||
return true;
|
||||
}
|
||||
|
@ -754,13 +764,14 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
private boolean generateComposition(XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
||||
boolean hasExtensions = false;
|
||||
List<String> langs = new ArrayList<String>();
|
||||
Map<String, String> designations = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list
|
||||
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
||||
scanForLangs(inc, langs);
|
||||
scanDesignations(inc, langs, designations);
|
||||
}
|
||||
for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
|
||||
scanForLangs(inc, langs);
|
||||
scanDesignations(inc, langs, designations);
|
||||
}
|
||||
boolean doLangs = langs.size() < MAX_LANGS_IN_LINE;
|
||||
boolean doDesignations = langs.size() + designations.size() < MAX_DESIGNATIONS_IN_LINE;
|
||||
|
||||
if (header) {
|
||||
XhtmlNode h = x.h2();
|
||||
|
@ -769,35 +780,48 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
if (vs.hasCopyrightElement())
|
||||
generateCopyright(x, vs);
|
||||
}
|
||||
int index = 0;
|
||||
if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0) {
|
||||
hasExtensions = genInclude(x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doLangs, maps) || hasExtensions;
|
||||
hasExtensions = genInclude(x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doDesignations, maps, designations, index) || hasExtensions;
|
||||
} else {
|
||||
XhtmlNode p = x.para();
|
||||
p.tx("This value set includes codes based on the following rules:");
|
||||
XhtmlNode ul = x.ul();
|
||||
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
||||
hasExtensions = genInclude(ul, inc, "Include", langs, doLangs, maps) || hasExtensions;
|
||||
hasExtensions = genInclude(ul, inc, "Include", langs, doDesignations, maps, designations, index) || hasExtensions;
|
||||
index++;
|
||||
}
|
||||
if (vs.getCompose().hasExclude()) {
|
||||
p = x.para();
|
||||
p.tx("This value set excludes codes based on the following rules:");
|
||||
ul = x.ul();
|
||||
for (ConceptSetComponent exc : vs.getCompose().getExclude()) {
|
||||
hasExtensions = genInclude(ul, exc, "Exclude", langs, doLangs, maps) || hasExtensions;
|
||||
hasExtensions = genInclude(ul, exc, "Exclude", langs, doDesignations, maps, designations, index) || hasExtensions;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now, build observed languages
|
||||
|
||||
if (!doLangs && langs.size() > 0) {
|
||||
if (!doDesignations && langs.size() + designations.size() > 0) {
|
||||
Collections.sort(langs);
|
||||
x.para().b().tx("Additional Language Displays");
|
||||
XhtmlNode t = x.table( "codes");
|
||||
if (designations.size() == 0) {
|
||||
x.para().b().tx("Additional Language Displays");
|
||||
} else if (langs.size() == 0) {
|
||||
x.para().b().tx("Additional Designations");
|
||||
} else {
|
||||
x.para().b().tx("Additional Designations and Language Displays");
|
||||
}
|
||||
XhtmlNode t = x.table("codes");
|
||||
XhtmlNode tr = t.tr();
|
||||
tr.td().b().tx("Code");
|
||||
for (String lang : langs)
|
||||
for (String url : designations.keySet()) {
|
||||
tr.td().b().addText(designations.get(url));
|
||||
}
|
||||
for (String lang : langs) {
|
||||
tr.td().b().addText(describeLang(lang));
|
||||
}
|
||||
for (ConceptSetComponent c : vs.getCompose().getInclude()) {
|
||||
for (ConceptReferenceComponent cc : c.getConcept()) {
|
||||
addLanguageRow(cc, t, langs);
|
||||
|
@ -805,10 +829,102 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return hasExtensions;
|
||||
}
|
||||
|
||||
private void scanForLangs(ConceptSetComponent inc, List<String> langs) {
|
||||
private void renderExpansionRules(XhtmlNode x, ConceptSetComponent inc, int index, Map<String, ConceptDefinitionComponent> definitions) throws FHIRException, IOException {
|
||||
String s = "This include specifies a heirarchy for when value sets are generated for use in a User Interface, but the rules are not properly defined";
|
||||
if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES)) {
|
||||
String rule = inc.getExtensionString(ToolingExtensions.EXT_EXPAND_RULES);
|
||||
if (rule != null) {
|
||||
switch (rule) {
|
||||
case "all-codes": s = "This include specifies a heirarchy for when value sets are generated for use in a User Interface. The expansion contains all the codes, and also this structure:";
|
||||
case "ungrouped": s = "This include specifies a heirarchy for when value sets are generated for use in a User Interface. The expansion contains this structure, and any codes not found in the structure:";
|
||||
case "groups-only": s = "This include specifies a heirarchy for when value sets are generated for use in a User Interface. The expansion contains this structure:";
|
||||
}
|
||||
}
|
||||
}
|
||||
x.br();
|
||||
x.tx(s);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
|
||||
TableModel model = gen.new TableModel("exp.h="+index, !forResource);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("vs.exp.header", "Code"), translate("vs.exp.hint", "The code for the item"), null, 0));
|
||||
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("vs.exp.header", "Display"), translate("vs.exp.hint", "The display for the item"), null, 0));
|
||||
|
||||
for (Extension ext : inc.getExtensionsByUrl(ToolingExtensions.EXT_EXPAND_GROUP)) {
|
||||
renderExpandGroup(gen, model, ext, inc, definitions);
|
||||
}
|
||||
x.br();
|
||||
x.tx("table");
|
||||
XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null);
|
||||
x.getChildNodes().add(xn);
|
||||
}
|
||||
|
||||
private void renderExpandGroup(HierarchicalTableGenerator gen, TableModel model, Extension ext, ConceptSetComponent inc, Map<String, ConceptDefinitionComponent> definitions) {
|
||||
Row row = gen.new Row();
|
||||
model.getRows().add(row);
|
||||
row.setIcon("icon_entry_blue.png", "entry");
|
||||
String code = ext.getExtensionString("code");
|
||||
if (code != null) {
|
||||
row.getCells().add(gen.new Cell(null, null, code, null, null));
|
||||
row.getCells().add(gen.new Cell(null, null, getDisplayForCode(inc, code, definitions), null, null));
|
||||
} else if (ext.hasId()) {
|
||||
row.getCells().add(gen.new Cell(null, null, "(#"+ext.getId()+")", null, null));
|
||||
row.getCells().add(gen.new Cell(null, null, ext.getExtensionString("display"), null, null));
|
||||
} else {
|
||||
row.getCells().add(gen.new Cell(null, null, null, null, null));
|
||||
row.getCells().add(gen.new Cell(null, null, ext.getExtensionString("display"), null, null));
|
||||
}
|
||||
for (Extension member : ext.getExtensionsByUrl("member")) {
|
||||
Row subRow = gen.new Row();
|
||||
row.getSubRows().add(subRow);
|
||||
subRow.setIcon("icon_entry_blue.png", "entry");
|
||||
String mc = member.getValue().primitiveValue();
|
||||
// mc might be a reference to another expansion group - we check that first, or to a code in the compose
|
||||
if (mc.startsWith("#")) {
|
||||
// it's a reference by id
|
||||
subRow.getCells().add(gen.new Cell(null, null, "("+mc+")", null, null));
|
||||
subRow.getCells().add(gen.new Cell(null, null, "group reference by id", null, null));
|
||||
} else {
|
||||
Extension tgt = findTargetByCode(inc, mc);
|
||||
if (tgt != null) {
|
||||
subRow.getCells().add(gen.new Cell(null, null, mc, null, null));
|
||||
subRow.getCells().add(gen.new Cell(null, null, "group reference by code", null, null));
|
||||
} else {
|
||||
subRow.getCells().add(gen.new Cell(null, null, mc, null, null));
|
||||
subRow.getCells().add(gen.new Cell(null, null, getDisplayForCode(inc, mc, definitions), null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Extension findTargetByCode(ConceptSetComponent inc, String mc) {
|
||||
for (Extension ext : inc.getExtensionsByUrl(ToolingExtensions.EXT_EXPAND_GROUP)) {
|
||||
String code = ext.getExtensionString("code");
|
||||
if (mc.equals(code)) {
|
||||
return ext;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getDisplayForCode(ConceptSetComponent inc, String code, Map<String, ConceptDefinitionComponent> definitions) {
|
||||
for (ConceptReferenceComponent cc : inc.getConcept()) {
|
||||
if (code.equals(cc.getCode())) {
|
||||
if (cc.hasDisplay()) {
|
||||
return cc.getDisplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (definitions.containsKey(code)) {
|
||||
return definitions.get(code).getDisplay();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void scanDesignations(ConceptSetComponent inc, List<String> langs, Map<String, String> designations) {
|
||||
for (ConceptReferenceComponent cc : inc.getConcept()) {
|
||||
for (Extension ext : cc.getExtension()) {
|
||||
if (ToolingExtensions.EXT_TRANSLATION.equals(ext.getUrl())) {
|
||||
|
@ -822,17 +938,47 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
String lang = d.getLanguage();
|
||||
if (!Utilities.noString(lang) && !langs.contains(lang)) {
|
||||
langs.add(lang);
|
||||
} else {
|
||||
// can we present this as a designation that we know?
|
||||
String url = getUrlForDesignation(d);
|
||||
String disp = getDisplayForUrl(url);
|
||||
if (disp != null && !designations.containsKey(url)) {
|
||||
designations.put(url, disp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doLangs, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
||||
private String getDisplayForUrl(String url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
switch (url) {
|
||||
case "http://snomed.info/sct#900000000000003001":
|
||||
return "Fully specified name";
|
||||
case "http://snomed.info/sct#900000000000013009":
|
||||
return "Synonym";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getUrlForDesignation(ConceptReferenceDesignationComponent d) {
|
||||
if (d.hasUse() && d.getUse().hasSystem() && d.getUse().hasCode()) {
|
||||
return d.getUse().getSystem()+"#"+d.getUse().getCode();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index) throws FHIRException, IOException {
|
||||
boolean hasExtensions = false;
|
||||
XhtmlNode li;
|
||||
li = ul.li();
|
||||
CodeSystem e = getContext().getWorker().fetchCodeSystem(inc.getSystem());
|
||||
|
||||
Map<String, ConceptDefinitionComponent> definitions = new HashMap<>();
|
||||
|
||||
if (inc.hasSystem()) {
|
||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||
li.addText(type+" all codes defined in ");
|
||||
|
@ -847,7 +993,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
|
||||
// for performance reasons, we do all the fetching in one batch
|
||||
Map<String, ConceptDefinitionComponent> definitions = getConceptsForCodes(e, inc);
|
||||
definitions = getConceptsForCodes(e, inc);
|
||||
|
||||
XhtmlNode t = li.table("none");
|
||||
boolean hasComments = false;
|
||||
|
@ -859,7 +1005,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
if (hasComments || hasDefinition)
|
||||
hasExtensions = true;
|
||||
addMapHeaders(addTableHeaderRowStandard(t, false, true, hasDefinition, hasComments, false, false, null, langs, doLangs), maps);
|
||||
addMapHeaders(addTableHeaderRowStandard(t, false, true, hasDefinition, hasComments, false, false, null, langs, designations, doDesignations), maps);
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
XhtmlNode tr = t.tr();
|
||||
XhtmlNode td = tr.td();
|
||||
|
@ -886,7 +1032,8 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
smartAddText(td, "Note: "+ToolingExtensions.readStringExtension(c, ToolingExtensions.EXT_VS_COMMENT));
|
||||
}
|
||||
}
|
||||
if (doLangs) {
|
||||
if (doDesignations) {
|
||||
addDesignationsToRow(c, designations, tr);
|
||||
addLangaugesToRow(c, langs, tr);
|
||||
}
|
||||
}
|
||||
|
@ -946,6 +1093,10 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
AddVsRef(vs.asStringValue(), li);
|
||||
}
|
||||
}
|
||||
if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES) || inc.hasExtension(ToolingExtensions.EXT_EXPAND_GROUP)) {
|
||||
hasExtensions = true;
|
||||
renderExpansionRules(li, inc, index, definitions);
|
||||
}
|
||||
} else {
|
||||
li.tx("Import all the codes that are contained in ");
|
||||
if (inc.getValueSet().size() < 4) {
|
||||
|
@ -968,6 +1119,20 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
return hasExtensions;
|
||||
}
|
||||
|
||||
public void addDesignationsToRow(ConceptReferenceComponent c, Map<String, String> designations, XhtmlNode tr) {
|
||||
for (String url : designations.keySet()) {
|
||||
String d = null;
|
||||
if (d == null) {
|
||||
for (ConceptReferenceDesignationComponent dd : c.getDesignation()) {
|
||||
if (url.equals(getUrlForDesignation(dd))) {
|
||||
d = dd.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
tr.td().addText(d == null ? "" : d);
|
||||
}
|
||||
}
|
||||
|
||||
public void addLangaugesToRow(ConceptReferenceComponent c, List<String> langs, XhtmlNode tr) {
|
||||
for (String lang : langs) {
|
||||
String d = null;
|
||||
|
|
|
@ -628,6 +628,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
break;
|
||||
}
|
||||
}
|
||||
i = valueset.getCompose().getInclude().size();
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getExclude()) {
|
||||
Boolean nok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
i++;
|
||||
|
|
|
@ -519,5 +519,8 @@ public class FHIRLexer {
|
|||
public int getCurrentStart() {
|
||||
return currentStart;
|
||||
}
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
|
@ -1000,7 +1000,9 @@ public class FHIRPathEngine {
|
|||
wrapper.setProximal(proximal);
|
||||
}
|
||||
|
||||
if (lexer.isConstant()) {
|
||||
if (lexer.getCurrent() == null) {
|
||||
throw lexer.error("Expression terminated unexpectedly");
|
||||
} else if (lexer.isConstant()) {
|
||||
boolean isString = lexer.isStringConstant();
|
||||
if (!isString && (lexer.getCurrent().startsWith("-") || lexer.getCurrent().startsWith("+"))) {
|
||||
// the grammar says that this is a unary operation; it affects the correct processing order of the inner operations
|
||||
|
|
|
@ -80,14 +80,14 @@ public class NPMPackageGenerator {
|
|||
private String getDirectory() {
|
||||
switch (this) {
|
||||
case RESOURCE: return "package/";
|
||||
case EXAMPLE: return "example/";
|
||||
case OPENAPI: return "openapi/";
|
||||
case SCHEMATRON: return "xml/";
|
||||
case RDF: return "rdf/";
|
||||
case OTHER: return "other/";
|
||||
case TEMPLATE: return "other/";
|
||||
case JEKYLL: return "jekyll/";
|
||||
case TOOL: return "bin/";
|
||||
case EXAMPLE: return "package/example/";
|
||||
case OPENAPI: return "package/openapi/";
|
||||
case SCHEMATRON: return "package/xml/";
|
||||
case RDF: return "package/rdf/";
|
||||
case OTHER: return "package/other/";
|
||||
case TEMPLATE: return "package/other/";
|
||||
case JEKYLL: return "package/jekyll/";
|
||||
case TOOL: return "package/bin/";
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ public class NPMPackageGenerator {
|
|||
public void addFile(Category cat, String name, byte[] content) throws IOException {
|
||||
String path = cat.getDirectory()+name;
|
||||
if (path.length() > 100) {
|
||||
name = name.substring(0, name.indexOf("-"))+"-"+UUID.randomUUID().toString();
|
||||
name = name.substring(0, name.indexOf("-"))+"-"+UUID.randomUUID().toString()+".json";
|
||||
path = cat.getDirectory()+name;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,10 @@ public class ResourceUtilities {
|
|||
if (cc.hasCoding("http://unstats.un.org/unsd/methods/m49/m49.htm", "001")) {
|
||||
return new Locale("en-US");
|
||||
}
|
||||
String c = cc.getCode("urn:iso:std:iso:3166:-2");
|
||||
String c = cc.getCode("urn:iso:std:iso:3166");
|
||||
if (c == null) {
|
||||
return null;
|
||||
}
|
||||
String l = jl.get(c);
|
||||
if (l == null) {
|
||||
return null;
|
||||
|
|
|
@ -198,6 +198,8 @@ public class ToolingExtensions {
|
|||
public static final String EXT_TARGET_ID = "http://hl7.org/fhir/StructureDefinition/targetElement";
|
||||
public static final String EXT_TARGET_PATH = "http://hl7.org/fhir/StructureDefinition/targetPath";
|
||||
public static final String EXT_VALUESET_SYSTEM = "http://hl7.org/fhir/StructureDefinition/valueset-system";
|
||||
public static final String EXT_EXPAND_RULES = "http://hl7.org/fhir/StructureDefinition/valueset-expand-rules";
|
||||
public static final String EXT_EXPAND_GROUP = "http://hl7.org/fhir/StructureDefinition/valueset-expand-group";
|
||||
|
||||
// specific extension helpers
|
||||
|
||||
|
@ -511,7 +513,7 @@ public class ToolingExtensions {
|
|||
* @return The extension, if on this element, else null
|
||||
*/
|
||||
public static Extension getExtension(DomainResource resource, String name) {
|
||||
if (name == null)
|
||||
if (resource == null || name == null)
|
||||
return null;
|
||||
if (!resource.hasExtension())
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.hl7.fhir.r5.utils.client.network;
|
||||
|
||||
import okhttp3.*;
|
||||
import okio.Buffer;
|
||||
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -26,8 +28,17 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
public Response intercept(@Nonnull Interceptor.Chain chain) throws IOException {
|
||||
// Log Request
|
||||
Request request = chain.request();
|
||||
logger.logRequest(request.method(), request.url().toString(), new ArrayList<>(request.headers().names()),
|
||||
request.body() != null ? request.body().toString().getBytes() : null);
|
||||
List<String> hdrs = new ArrayList<>();
|
||||
for (String s : request.headers().toString().split("\\n")) {
|
||||
hdrs.add(s.trim());
|
||||
}
|
||||
byte[] cnt = null;
|
||||
if (request.body() != null) {
|
||||
Buffer buf = new Buffer();
|
||||
request.body().writeTo(buf);
|
||||
cnt = buf.readByteArray();
|
||||
}
|
||||
logger.logRequest(request.method(), request.url().toString(), hdrs, cnt);
|
||||
|
||||
// Log Response
|
||||
Response response = null;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ public class SimpleHTTPClient {
|
|||
|
||||
public HTTPResult get(String url, String accept) throws IOException {
|
||||
URL u = new URL(url);
|
||||
boolean isSSL = url.startsWith("https://");
|
||||
// boolean isSSL = url.startsWith("https://");
|
||||
|
||||
// handling redirects - setInstanceFollowRedirects(true) doesn't handle crossing http to https
|
||||
|
||||
|
|
|
@ -649,7 +649,7 @@ public class Utilities {
|
|||
StringBuilder s = new StringBuilder();
|
||||
boolean d = false;
|
||||
for (String arg : args) {
|
||||
if (args != null) {
|
||||
if (arg != null) {
|
||||
if (!d)
|
||||
d = !noString(arg);
|
||||
else if (s.toString() != null && !s.toString().endsWith("/") && !arg.startsWith("/"))
|
||||
|
@ -660,14 +660,6 @@ public class Utilities {
|
|||
return s.toString();
|
||||
}
|
||||
|
||||
|
||||
// public static void checkCase(String filename) {
|
||||
// File f = new CSFile(filename);
|
||||
// if (!f.getName().equals(filename))
|
||||
// throw new FHIRException("Filename ")
|
||||
//
|
||||
// }
|
||||
|
||||
public static String nmtokenize(String cs) {
|
||||
if (cs == null)
|
||||
return "";
|
||||
|
|
|
@ -134,7 +134,7 @@ public class VersionUtilities {
|
|||
}
|
||||
|
||||
public static String listSupportedVersions() {
|
||||
return "1.0.2, 1.4.0, 3.0.2, 4.0.1, 4.1.0, 4.3.0, 5.0, "+CURRENT_FULL_VERSION;
|
||||
return "1.0.2, 1.4.0, 3.0.2, 4.0.1, 4.1.0, 4.3.0, 5.0, " + CURRENT_FULL_VERSION;
|
||||
}
|
||||
|
||||
public static boolean isR5Ver(String ver) {
|
||||
|
|
|
@ -246,7 +246,7 @@ All_observations_should_have_a_performer = All observations should have a perfor
|
|||
All_observations_should_have_a_subject = All observations should have a subject
|
||||
Unable_to_resolve_slice_matching__no_fixed_value_or_required_value_set = Unable to resolve slice matching - no fixed value or required value set
|
||||
Unable_to_resolve_slice_matching__slice_matching_by_value_set_not_done = Unable to resolve slice matching - slice matching by value set not done
|
||||
Problem_processing_expression__in_profile__path__ = Problem processing expression {0} in profile {1} path {2}: {3}
|
||||
Problem_processing_expression__in_profile__path__ = Problem processing expression ''{0}'' in profile ''{1}'' at path ''{2}'': {3}
|
||||
Unable_to_find_element_with_id_ = Unable to find element with id ''{0}''
|
||||
Slice_encountered_midway_through_set_path___id___ = Slice encountered midway through set (path = {0}, id = {1}); {2}
|
||||
Unable_to_resolve_actual_type_ = Unable to resolve actual type {0}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -54,6 +54,10 @@
|
|||
<artifactId>okhttp</artifactId>
|
||||
<version>4.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.atlassian.commonmark</groupId>
|
||||
<artifactId>commonmark</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -167,6 +167,13 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.atlassian.commonmark</groupId>
|
||||
<artifactId>commonmark</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
|
@ -228,6 +235,24 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven_surefire_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes combine.children="override">
|
||||
<exclude>org/hl7/fhir/validation/cli/services/ValidationServiceTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
|
|
|
@ -588,7 +588,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
private void handleOutputToStream(Resource r, String fn, OutputStream s, String version) throws FHIRException, IOException {
|
||||
if (fn.endsWith(".html") || fn.endsWith(".htm") && r instanceof DomainResource)
|
||||
new XhtmlComposer(XhtmlComposer.HTML, true).compose(s, ((DomainResource) r).getText().getDiv());
|
||||
else if (version.startsWith("3.0")) {
|
||||
else if (VersionUtilities.isR3Ver(version)) {
|
||||
org.hl7.fhir.dstu3.model.Resource res = VersionConvertorFactory_30_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new org.hl7.fhir.dstu3.formats.XmlParser().setOutputStyle(org.hl7.fhir.dstu3.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
|
@ -598,7 +598,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
TextFile.stringToStream(org.hl7.fhir.dstu3.utils.StructureMapUtilities.render((org.hl7.fhir.dstu3.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new FHIRException("Unsupported format for " + fn);
|
||||
} else if (version.startsWith("4.0")) {
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
org.hl7.fhir.r4.model.Resource res = VersionConvertorFactory_40_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new org.hl7.fhir.r4.formats.XmlParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
|
@ -608,7 +608,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
TextFile.stringToStream(org.hl7.fhir.r4.utils.StructureMapUtilities.render((org.hl7.fhir.r4.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new FHIRException("Unsupported format for " + fn);
|
||||
} else if (version.startsWith("1.4")) {
|
||||
} else if (VersionUtilities.isR2BVer(version)) {
|
||||
org.hl7.fhir.dstu2016may.model.Resource res = VersionConvertorFactory_14_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new org.hl7.fhir.dstu2016may.formats.XmlParser().setOutputStyle(org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
|
@ -616,7 +616,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
new org.hl7.fhir.dstu2016may.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new FHIRException("Unsupported format for " + fn);
|
||||
} else if (version.startsWith("1.0")) {
|
||||
} else if (VersionUtilities.isR2Ver(version)) {
|
||||
org.hl7.fhir.dstu2.model.Resource res = VersionConvertorFactory_10_50.convertResource(r, new org.hl7.fhir.convertors.misc.IGR2ConvertorAdvisor5());
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
|
@ -624,7 +624,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new FHIRException("Unsupported format for " + fn);
|
||||
} else if (version.equals(Constants.VERSION)) {
|
||||
} else if (VersionUtilities.isR5Ver(version)) {
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new XmlParser().setOutputStyle(org.hl7.fhir.r5.formats.IParser.OutputStyle.PRETTY).compose(s, r);
|
||||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
|
|
|
@ -2,12 +2,16 @@ package org.hl7.fhir.validation.cli.utils;
|
|||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.r5.model.Constants;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.ToolsVersion;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class for displaying output to the cli user.
|
||||
|
@ -16,6 +20,7 @@ import java.io.InputStream;
|
|||
*/
|
||||
public class Display {
|
||||
|
||||
|
||||
private static String toMB(long maxMemory) {
|
||||
return Long.toString(maxMemory / (1024 * 1024));
|
||||
}
|
||||
|
@ -29,6 +34,29 @@ public class Display {
|
|||
System.out.println();
|
||||
}
|
||||
|
||||
final static String CURLY_START = "\\{\\{";
|
||||
final static String CURLY_END = "\\}\\}";
|
||||
|
||||
final static String getMoustacheString(final String string) {
|
||||
return CURLY_START + string + CURLY_END;
|
||||
}
|
||||
|
||||
final static String[][] PLACEHOLDERS = {
|
||||
{ getMoustacheString("XML_AND_JSON_FHIR_VERSIONS"), "1.0, 1.4, 3.0, 4.0," + Constants.VERSION_MM },
|
||||
{ getMoustacheString("TURTLE_FHIR_VERSIONS"), "3.0, 4.0, " + Constants.VERSION_MM },
|
||||
{ getMoustacheString("FHIR_MAJOR_VERSIONS"), "1.0|1.4|3.0|" + VersionUtilities.CURRENT_VERSION},
|
||||
{ getMoustacheString("FHIR_MINOR_VERSIONS"), "1.0.2|1.4.0|3.0.2|4.0.1|" + VersionUtilities.CURRENT_FULL_VERSION },
|
||||
{ getMoustacheString("FHIR_CURRENT_VERSION"), VersionUtilities.CURRENT_VERSION},
|
||||
};
|
||||
|
||||
final static String replacePlaceholders(final String input, final String[][] placeholders) {
|
||||
String output = input;
|
||||
for (String[] placeholder : placeholders) {
|
||||
output = output.replaceAll(placeholder[0], placeholder[1]);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the help details from resources/help.txt, and displays them on the command line to the user.
|
||||
*/
|
||||
|
@ -37,12 +65,15 @@ public class Display {
|
|||
InputStream help = classLoader.getResourceAsStream("help.txt");
|
||||
try {
|
||||
String data = IOUtils.toString(help, "UTF-8");
|
||||
System.out.println(data);
|
||||
|
||||
System.out.println(replacePlaceholders(data, PLACEHOLDERS));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prints out system info to the command line.
|
||||
*/
|
||||
|
|
|
@ -5490,7 +5490,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
try {
|
||||
n = fpe.parse(fixExpr(inv.getExpression(), inv.getKey()));
|
||||
} catch (FHIRLexerException e) {
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.PROBLEM_PROCESSING_EXPRESSION__IN_PROFILE__PATH__, inv.getExpression(), profile.getUrl(), path, e.getMessage()));
|
||||
rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, false, I18nConstants.PROBLEM_PROCESSING_EXPRESSION__IN_PROFILE__PATH__, inv.getExpression(), profile.getUrl(), path, e.getMessage());
|
||||
return;
|
||||
}
|
||||
timeTracker.fpe(t);
|
||||
inv.setUserData("validator.expression.cache", n);
|
||||
|
|
|
@ -6,8 +6,8 @@ command line
|
|||
|
||||
The FHIR validation tool validates a FHIR resource or bundle.
|
||||
Schema and schematron checking is performed, then some additional checks are performed.
|
||||
* XML & Json (FHIR versions 1.0, 1.4, 3.0, 4.0, " + Constants.VERSION_MM + ")
|
||||
* Turtle (FHIR versions 3.0, 4.0, " + Constants.VERSION_MM + ")
|
||||
* XML & Json (FHIR versions {{XML_AND_JSON_FHIR_VERSIONS}})
|
||||
* Turtle (FHIR versions {{TURTLE_FHIR_VERSIONS}})
|
||||
|
||||
If requested, instances will also be verified against the appropriate schema
|
||||
W3C XML Schema, JSON schema or ShEx, as appropriate
|
||||
|
@ -22,8 +22,8 @@ The following parameters are supported:
|
|||
Patterns are limited to a directory followed by a filename with an embedded
|
||||
asterisk. E.g. foo*-examples.xml or someresource.*, etc.
|
||||
-version [ver]: The FHIR version to use. This can only appear once.
|
||||
valid values 1.0 | 1.4 | 3.0 | " + VersionUtilities.CURRENT_VERSION + " or 1.0.2 | 1.4.0 | 3.0.2 | 4.0.1 | " + VersionUtilities.CURRENT_FULL_VERSION);
|
||||
Default value is " + VersionUtilities.CURRENT_VERSION);
|
||||
valid values {{FHIR_MAJOR_VERSIONS}} or {{FHIR_MINOR_VERSIONS}}
|
||||
Default value is {{FHIR_CURRENT_VERSION}}
|
||||
-ig [package|file|folder|url]: an IG or profile definition to load. Can be
|
||||
the URL of an implementation guide or a package ([id]-[ver]) for
|
||||
a built implementation guide or a local folder that contains a
|
||||
|
@ -48,7 +48,7 @@ The following parameters are supported:
|
|||
-showReferenceMessages
|
||||
Includes validation messages resulting from validating target resources
|
||||
against profiles defined on a reference. This increases the volume of
|
||||
validationmessages, but may allow easier debugging. If not specified,
|
||||
validation messages, but may allow easier debugging. If not specified,
|
||||
then only a high-level message indicating that the referenced item wasn't
|
||||
valid against the listed profile(s) will be provided.
|
||||
-questionnaire mode: what to do with when validating QuestionnaireResponse resources
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import org.hl7.fhir.validation.cli.utils.Display;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class DisplayTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Check for placeholder replacement in help output")
|
||||
public void displayHelpDetails() {
|
||||
final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
|
||||
final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
|
||||
|
||||
final PrintStream originalOut = System.out;
|
||||
final PrintStream originalErr = System.err;
|
||||
|
||||
System.setOut(new PrintStream(outContent));
|
||||
System.setErr(new PrintStream(errContent));
|
||||
|
||||
try {
|
||||
Display.displayHelpDetails();
|
||||
|
||||
String output = outContent.toString();
|
||||
|
||||
for (String[] placeHolder: Display.PLACEHOLDERS) {
|
||||
assertTrue(output.contains(placeHolder[1]), placeHolder[1] + " is not contained in output:\n" + output);
|
||||
assertFalse(output.contains(placeHolder[0]), placeHolder[0] + " found in output:\n" + output);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
System.setOut(originalOut);
|
||||
System.setErr(originalErr);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test replacePlaceholder base case")
|
||||
public void testReplacePlaceholdersBaseCase() {
|
||||
|
||||
final String myTestString = "The {{DUMMY_A}} jumps over the {{DUMMY_B}}.";
|
||||
final String[][] placeHolders = {
|
||||
{ "\\{\\{DUMMY_A\\}\\}", "quick brown fox"},
|
||||
{ "\\{\\{DUMMY_B\\}\\}", "lazy dog"},
|
||||
};
|
||||
|
||||
final String expectedOutput = "The quick brown fox jumps over the lazy dog.";
|
||||
final String output = Display.replacePlaceholders(myTestString, placeHolders);
|
||||
|
||||
assertEquals(expectedOutput, output);
|
||||
}
|
||||
|
||||
}
|
4
pom.xml
4
pom.xml
|
@ -14,12 +14,12 @@
|
|||
HAPI FHIR
|
||||
-->
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.23-SNAPSHOT</version>
|
||||
<version>5.6.26-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||
<validator_test_case_version>1.1.86</validator_test_case_version>
|
||||
<validator_test_case_version>1.1.87</validator_test_case_version>
|
||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
||||
<maven_surefire_version>3.0.0-M5</maven_surefire_version>
|
||||
|
|
Loading…
Reference in New Issue