This commit is contained in:
Lloyd McKenzie 2024-11-13 21:39:32 -07:00
commit bbb7b0c88a
86 changed files with 832 additions and 447 deletions

View File

@ -1,23 +1,7 @@
## Validator Changes
* Fix issue where valdiator not retaining extension context when checking constraint expressions in profiles
* Validate min-length when found in extension
* Correct bug parsing json-property-key values with meant validation failed
* Fix problem validating json-property-key value pairs
* Fix special case r5 loading of terminology to fix validation error on ExampleScenario
* Improve handling of JSON format errors
* Fix slicing by type and profile to allow multiple options per slice
* List measure choices when a match by version can't be found
* Validate fhirpath expression in slice discriminators
* no changes
## Other code changes
* More work on code generation for profiles
* Render min-length extension on profiles
* Clone SQL on FHIR engine to R4, and update FHIRPath engine based on R5 current code
* Update SQL on FHIR engine to allow push as well as pull
* Change R5 tx server to use http://tx.fhir.org/r5 (instead of /r4)
* Update output from tx-tester to include release ready statement
* Fix rendering of Logical Models for polymorphic elements, and rendering target profiles with versions
* Render contained resources in List resource
* #1790 - Fix versionFromCanonical returns system instead and systemFromCanonical returns version
* Test Release

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,5 +1,5 @@
Locale,Coverage #,Coverage %
de,831,40%
es,714,34%
ja,902,43%
nl,1988,96%
de,829,40%
es,712,34%
ja,900,43%
nl,1986,96%

1 Locale Coverage # Coverage %
2 de 831 829 40%
3 es 714 712 34%
4 ja 902 900 43%
5 nl 1988 1986 96%

View File

@ -117,6 +117,7 @@ jobs:
# This is done for the master branch merges only.
- task: Maven@4
displayName: 'Deploy to GitHub packages'
enabled: false
inputs:
mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml'
goals: jar:jar deploy:deploy
@ -196,4 +197,4 @@ jobs:
git push https://$(GIT_PAT)@github.com/hapifhir/org.hl7.fhir.core.git
displayName: 'Push updated csv and plot to git.'
displayName: 'Push updated csv and plot to git.'

View File

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

View File

@ -3,12 +3,7 @@ package org.hl7.fhir.convertors.analytics;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import javax.xml.parsers.ParserConfigurationException;
@ -241,7 +236,7 @@ public class PackageVisitor {
File co = ManagedFileAccess.file(Utilities.path(cache, pid+"."+manifest.asString("date")+".tgz"));
if (!co.exists()) {
HTTPResult res = ManagedWebAccess.get(repo+"/package.tgz?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), repo+"/package.tgz?nocache=" + System.currentTimeMillis());
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), co);
}
@ -338,7 +333,7 @@ public class PackageVisitor {
System.out.println("Feed "+str);
try {
HTTPResult res = ManagedWebAccess.get(str+"?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), str+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
Document xml = XMLUtil.parseToDom(res.getContent());
for (Element channel : XMLUtil.getNamedChildren(xml.getDocumentElement(), "channel")) {

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
@ -126,7 +127,7 @@ public class CKMImporter {
private Document loadXml(String address) throws Exception {
HTTPResult res = ManagedWebAccess.get(address, "application/xml");
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), address, "application/xml");
res.checkThrowException();
InputStream xml = new ByteArrayInputStream(res.getContent());

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.convertors.misc;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@ -394,7 +395,7 @@ public class ICD11Generator {
private JsonObject fetchJson(String source) throws IOException {
HTTPResult res = ManagedWebAccess.accessor().withHeader("API-Version", "v2").withHeader("Accept-Language", "en").get(source,"application/json");
HTTPResult res = ManagedWebAccess.accessor(Arrays.asList("web")).withHeader("API-Version", "v2").withHeader("Accept-Language", "en").get(source,"application/json");
res.checkThrowException();
return JsonParser.parseObject(res.getContent());
}

View File

@ -163,6 +163,11 @@ public class TerminologyClientR2 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_10_50.convertResource(client.lookupCode(params));

View File

@ -153,6 +153,11 @@ public class TerminologyClientR3 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_30_50.convertResource(client.lookupCode(params));

View File

@ -64,7 +64,7 @@ public class TerminologyClientR4 implements ITerminologyClient {
}
public FhirPublication getActualVersion() {
return FhirPublication.STU3;
return FhirPublication.R4;
}
@ -177,6 +177,11 @@ public class TerminologyClientR4 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params));

View File

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

View File

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

View File

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

View File

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

View File

@ -31,12 +31,7 @@ package org.hl7.fhir.r4.conformance;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
@ -1384,7 +1379,7 @@ public class ProfileComparer {
if (f.exists())
return TextFile.fileToString(f);
HTTPResult res = ManagedWebAccess.get(source);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source);
res.checkThrowException();
String result = TextFile.bytesToString(res.getContent());
TextFile.stringToFile(result, f);

View File

@ -71,7 +71,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@Setter
private ResourceFormat preferredResourceFormat;
private int maxResultSetSize = -1;// _count
private CapabilityStatement capabilities;
@Getter
@Setter
private Client client = new Client();
@ -100,13 +99,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
this.maxResultSetSize = -1;
}
private void checkCapabilities() {
try {
capabilities = getCapabilitiesStatementQuick();
} catch (Throwable e) {
}
}
public String getPreferredResourceFormat() {
return preferredResourceFormat.getHeader();
}
@ -130,10 +122,10 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
return capabilities;
}
public CapabilityStatement getCapabilitiesStatement() {
public CapabilityStatement getCapabilitiesStatementQuick() {
CapabilityStatement conformance = null;
try {
conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement", timeoutNormal).getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's conformance statement", e);
@ -141,18 +133,15 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
return conformance;
}
public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException {
if (capabilities != null)
return capabilities;
try {
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal)
.getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e);
}
return capabilities;
}
public CapabilityStatement getCapabilitiesStatement() throws EFhirClientException {
try {
return (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal)
.getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e);
}
}
public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
@ -562,8 +551,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
}
public String getServerVersion() {
checkCapabilities();
return capabilities == null ? null : capabilities.getSoftware().getVersion();
return getCapabilitiesStatementQuick().getSoftware().getVersion();
}
public Bundle search(String type, String criteria) {

View File

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

View File

@ -61,11 +61,11 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
file.println("\r\n--- " + id + " -----------------\r\nRequest: \r\n");
file.println(method + " " + url + " HTTP/1.0");
for (String s : headers)
file.println(Utilities.escapeXml(s));
file.println(s);
if (body != null) {
file.println("");
try {
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
file.println(new String(body, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}
@ -82,7 +82,7 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
if (body != null) {
file.println("");
try {
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
file.println(new String(body, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}

View File

@ -9,6 +9,7 @@ import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -79,7 +80,7 @@ public class TerminologyCacheManager {
try {
System.out.println("Initialise terminology cache from " + source);
HTTPResult res = ManagedWebAccess.get(source + "?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
unzip(new ByteArrayInputStream(res.getContent()), cacheFolder);
} catch (Exception e) {
@ -148,7 +149,7 @@ public class TerminologyCacheManager {
String url = "https://tx.fhir.org/post/tx-cache/" + ghOrg + "/" + ghRepo + "/" + ghBranch + ".zip";
System.out.println("Sending tx-cache to " + url + " (" + Utilities.describeSize(bs.toByteArray().length) + ")");
HTTPResult res = ManagedWebAccess.accessor()
HTTPResult res = ManagedWebAccess.accessor(Arrays.asList("web"))
.withBasicAuth(token.substring(0, token.indexOf(':')), token.substring(token.indexOf(':') + 1))
.put(url, bs.toByteArray(), null, "application/zip");
if (res.getCode() >= 300) {

View File

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

View File

@ -119,6 +119,7 @@ import org.hl7.fhir.utilities.xml.SchematronWriter.Rule;
import org.hl7.fhir.utilities.xml.SchematronWriter.SchematronType;
import org.hl7.fhir.utilities.xml.SchematronWriter.Section;
/**
* This class provides a set of utility operations for working with Profiles.
* Key functionality:
@ -490,8 +491,8 @@ public class ProfileUtilities {
return this;
}
public SourcedChildDefinitions getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
String cacheKey = "cm."+profile.getVersionedUrl()+"#"+(element.hasId() ? element.getId() : element.getPath());
public SourcedChildDefinitions getChildMap(StructureDefinition profile, ElementDefinition element, boolean chaseTypes) throws DefinitionException {
String cacheKey = "cm."+profile.getVersionedUrl()+"#"+(element.hasId() ? element.getId() : element.getPath())+"."+chaseTypes;
if (childMapCache.containsKey(cacheKey)) {
return childMapCache.get(cacheKey);
}
@ -519,7 +520,7 @@ public class ProfileUtilities {
for (ElementDefinition e : list) {
if (id.equals(e.getId()))
return getChildMap(src, e);
return getChildMap(src, e, true);
}
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_NAME_REFERENCE__AT_PATH_, element.getContentReference(), element.getPath()));
@ -536,6 +537,30 @@ public class ProfileUtilities {
} else
break;
}
if (res.isEmpty() && chaseTypes) {
// we've got no in-line children. Some consumers of this routine will figure this out for themselves but most just want to walk into
// the type children.
src = null;
if (element.getType().isEmpty()) {
throw new DefinitionException("No defined children and no type information on element '"+element.getId()+"'");
} else if (element.getType().size() > 1) {
throw new DefinitionException("No defined children and multiple possible types '"+element.typeSummary()+"' on element '"+element.getId()+"'");
} else if (element.getType().get(0).getProfile().size() > 1) {
throw new DefinitionException("No defined children and multiple possible type profiles '"+element.typeSummary()+"' on element '"+element.getId()+"'");
} else if (element.getType().get(0).hasProfile()) {
src = context.fetchResource(StructureDefinition.class, element.getType().get(0).getProfile().get(0).getValue());
if (src == null) {
throw new DefinitionException("No defined children and unknown type profile '"+element.typeSummary()+"' on element '"+element.getId()+"'");
}
} else {
src = context.fetchTypeDefinition(element.getType().get(0).getWorkingCode());
if (src == null) {
throw new DefinitionException("No defined children and unknown type '"+element.typeSummary()+"' on element '"+element.getId()+"'");
}
}
SourcedChildDefinitions scd = getChildMap(src, src.getSnapshot().getElementFirstRep(), false);
res = scd.list;
}
SourcedChildDefinitions result = new SourcedChildDefinitions(src, res);
childMapCache.put(cacheKey, result);
return result;
@ -4085,7 +4110,7 @@ public class ProfileUtilities {
private org.hl7.fhir.r5.elementmodel.Element generateExample(StructureDefinition profile, ExampleValueAccessor accessor) throws FHIRException {
ElementDefinition ed = profile.getSnapshot().getElementFirstRep();
org.hl7.fhir.r5.elementmodel.Element r = new org.hl7.fhir.r5.elementmodel.Element(ed.getPath(), new Property(context, ed, profile));
SourcedChildDefinitions children = getChildMap(profile, ed);
SourcedChildDefinitions children = getChildMap(profile, ed, true);
for (ElementDefinition child : children.getList()) {
if (child.getPath().endsWith(".id")) {
org.hl7.fhir.r5.elementmodel.Element id = new org.hl7.fhir.r5.elementmodel.Element("id", new Property(context, child, profile));
@ -4107,7 +4132,7 @@ public class ProfileUtilities {
} else {
org.hl7.fhir.r5.elementmodel.Element res = new org.hl7.fhir.r5.elementmodel.Element(tail(ed.getPath()), new Property(context, ed, profile));
boolean hasValue = false;
SourcedChildDefinitions children = getChildMap(profile, ed);
SourcedChildDefinitions children = getChildMap(profile, ed, true);
for (ElementDefinition child : children.getList()) {
if (!child.hasContentReference()) {
org.hl7.fhir.r5.elementmodel.Element e = createExampleElement(profile, child, accessor);

View File

@ -93,7 +93,7 @@ public class ObjectConverter {
if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE)
res.setValue(((PrimitiveType) base).asStringValue());
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep(), true);
for (ElementDefinition child : children.getList()) {
String n = tail(child.getPath());
if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {

View File

@ -385,7 +385,7 @@ public class Property {
ElementDefinition ed = definition;
StructureDefinition sd = structure;
boolean isCDA = isCDAElement(structure);
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed);
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed, false);
String url = null;
if (children.getList().isEmpty() || isElementWithOnlyExtension(ed, children.getList())) {
// ok, find the right definitions
@ -459,7 +459,7 @@ public class Property {
sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null)
throw new DefinitionException("Unable to find definition '"+url+"' for type '"+t+"' for name '"+elementName+"' on property "+definition.getPath());
children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0));
children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0), false);
}
}
List<Property> properties = new ArrayList<Property>();
@ -493,7 +493,7 @@ public class Property {
protected List<Property> getChildProperties(TypeDetails type) throws DefinitionException {
ElementDefinition ed = definition;
StructureDefinition sd = structure;
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed);
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed, false);
if (children.getList().isEmpty()) {
// ok, find the right definitions
String t = null;
@ -519,7 +519,7 @@ public class Property {
sd = context.fetchResource(StructureDefinition.class, t);
if (sd == null)
throw new DefinitionException("Unable to find class '"+t+"' for name '"+ed.getPath()+"' on property "+definition.getPath());
children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0));
children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0), false);
}
}
List<Property> properties = new ArrayList<Property>();

View File

@ -29,6 +29,9 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.http.HTTPRequest;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonElement;
@ -428,6 +431,20 @@ public class SHCParser extends ParserBase {
private String getVCIIssuer(List<ValidationMessage> errors, String issuer) {
try {
JsonObject vci = org.hl7.fhir.utilities.json.parser.JsonParser.parseObjectFromUrl("https://raw.githubusercontent.com/the-commons-project/vci-directory/main/vci-issuers.json");
/* HTTPResult httpResult = ManagedWebAccess.httpCall(
new HTTPRequest().withMethod(HTTPVerb.GET).withUrl(new URL("https://raw.githubusercontent.com/the-commons-project/vci-directory/main/vci-issuers.json"))
new URL("https://raw.githubusercontent.com/the-commons-project/vci-directory/main/vci-issuers.json")
HTTPRequest.HttpMethod.GET,
null,
null,
null
)
)
*/
//JsonObject vci = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject();
for (JsonObject j : vci.getJsonObjects("participating_issuers")) {
if (issuer.equals(j.asString("iss"))) {
return j.asString("name");

View File

@ -287,7 +287,7 @@ public class SHLParser extends ParserBase {
private HTTPResult fetchFile(String url, String ct) throws IOException {
HTTPResult res = ManagedWebAccess.get(url, ct);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), url, ct);
res.checkThrowException();
return res;
}
@ -299,7 +299,7 @@ public class SHLParser extends ParserBase {
JsonObject j = new JsonObject();
j.add("recipient", "FHIR Validator");
HTTPResult res = ManagedWebAccess.post(url, org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j), "application/json", "application/json");
HTTPResult res = ManagedWebAccess.post(Arrays.asList("web"), url, org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j), "application/json", "application/json");
res.checkThrowException();
return res;
}

View File

@ -6619,7 +6619,7 @@ public class FHIRPathEngine {
focus = element;
} else {
SourcedChildDefinitions childDefinitions;
childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
childDefinitions = profileUtilities.getChildMap(sd, element.getElement(), false);
// if that's empty, get the children of the type
if (childDefinitions.getList().isEmpty()) {
@ -6627,7 +6627,7 @@ public class FHIRPathEngine {
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getElement().getType().get(0).getProfile(), element.getElement().getId());
}
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep(), false);
}
for (ElementDefinition t : childDefinitions.getList()) {
if (tailMatches(t, expr.getName()) && !t.hasSlicing()) { // GG: slicing is a problem here. This is for an exetnsion with a fixed value (type slicing)
@ -6657,7 +6657,7 @@ public class FHIRPathEngine {
focus = new TypedElementDefinition(sd.getSnapshot().getElementFirstRep());
} else if ("extension".equals(expr.getName())) {
String targetUrl = expr.getParameters().get(0).getConstant().primitiveValue();
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(sd, element.getElement(), true);
for (ElementDefinition t : childDefinitions.getList()) {
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
@ -6666,7 +6666,7 @@ public class FHIRPathEngine {
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition(), exsd);
}
if (exsd != null && exsd.getUrl().equals(targetUrl)) {
if (profileUtilities.getChildMap(sd, t).getList().isEmpty()) {
if (profileUtilities.getChildMap(sd, t, false).getList().isEmpty()) {
sd = exsd;
}
focus = new TypedElementDefinition(t);

View File

@ -99,7 +99,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
if (sd == null)
return "unknown resource " +res.fhirType();
else {
SourcedChildDefinitions childDefs = context.getProfileUtilities().getChildMap(sd, ed);
SourcedChildDefinitions childDefs = context.getProfileUtilities().getChildMap(sd, ed, true);
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("; ");
for (NamedResourceWrapperList p : res.childrenInGroups()) {
ElementDefinition pDefn = getElementDefinition(childDefs, p);

View File

@ -9,6 +9,7 @@ import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -78,7 +79,7 @@ public class TerminologyCacheManager {
try {
System.out.println("Initialise terminology cache from "+source);
HTTPResult res = ManagedWebAccess.get(source+"?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
unzip(new ByteArrayInputStream(res.getContent()), cacheFolder);
} catch (Exception e) {
@ -148,7 +149,7 @@ public class TerminologyCacheManager {
// post it to
String url = "https://tx.fhir.org/post/tx-cache/"+ghOrg+"/"+ghRepo+"/"+ghBranch+".zip";
System.out.println("Sending tx-cache to "+url+" ("+Utilities.describeSize(bs.toByteArray().length)+")");
HTTPResult res = ManagedWebAccess.accessor()
HTTPResult res = ManagedWebAccess.accessor(Arrays.asList("web"))
.withBasicAuth(token.substring(0, token.indexOf(':')), token.substring(token.indexOf(':') + 1))
.put(url, bs.toByteArray(), null, "application/zip");

View File

@ -60,6 +60,7 @@ public interface ITerminologyClient {
ITerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException;
int getRetryCount() throws FHIRException;
ITerminologyClient setRetryCount(int retryCount) throws FHIRException;
CapabilityStatement getCapabilitiesStatement() throws FHIRException;
CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException;
Parameters lookupCode(Map<String, String> params) throws FHIRException;
Parameters lookupCode(Parameters params) throws FHIRException;

View File

@ -165,6 +165,11 @@ public class TerminologyClientR5 implements ITerminologyClient {
return client.getCapabilitiesStatementQuick();
}
@Override
public CapabilityStatement getCapabilitiesStatement() {
return client.getCapabilitiesStatement();
}
@Override
public Parameters lookupCode(Map<String, String> params) {
return client.lookupCode(params);

View File

@ -3,6 +3,7 @@ package org.hl7.fhir.r5.test.utils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.utilities.*;
import org.hl7.fhir.utilities.filesystem.CSFile;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
@ -27,6 +28,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -34,12 +36,51 @@ public class CompareUtilities extends BaseTestingUtilities {
private static final boolean SHOW_DIFF = false;
private JsonObject externals;
private Map<String, String> variables;
private boolean patternMode;
public CompareUtilities() {
super();
this.variables = new HashMap<String, String>();
}
public CompareUtilities(JsonObject externals) {
super();
this.externals = externals;
this.variables = new HashMap<String, String>();
}
public CompareUtilities(JsonObject externals, Map<String, String> variables) {
super();
this.externals = externals;
this.variables = variables;
}
/**
* in pattern mode, the comparison is only looking to find the expected properties. anything else is ignored
* @return
*/
public boolean isPatternMode() {
return patternMode;
}
public CompareUtilities setPatternMode(boolean patternMode) {
this.patternMode = patternMode;
return this;
}
public String createNotEqualMessage(String id, final String message, final String expected, final String actual) {
if (patternMode) {
return new StringBuilder()
.append(message).append('\n')
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n')
.append(message).append(". ")
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append(". ")
.append("Actual :").append("\""+actual+"\"").toString();
} else {
return new StringBuilder()
.append(message).append('\n')
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n')
.append("Actual :").append("\""+actual+"\"").toString();
}
}
private String presentExpected(String expected) {
@ -64,8 +105,13 @@ public class CompareUtilities extends BaseTestingUtilities {
switch (expected) {
case "$$" : return "$$";
case "$instant$": return "\"An Instant\"";
case "$date$": return "\"A date\"";
case "$uuid$": return "\"A Uuid\"";
case "$string$": return "\"A string\"";
case "$id$": return "\"An Id\"";
case "$url$": return "\"A URL\"";
case "$token$": return "\"A Token\"";
case "$version$": return variables.containsKey("version") ? variables.get("version") : "(anything)";
default: return "Unhandled template: "+expected;
}
}
@ -74,15 +120,13 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
public static String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception {
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(id, expected, actual);
public String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception {
String result = compareXml(id, expected, actual);
return result;
}
public static String checkXMLIsSame(String id, String expected, String actual) throws Exception {
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(id, expected, actual);
public String checkXMLIsSame(String id, String expected, String actual) throws Exception {
String result = compareXml(id, expected, actual);
if (result != null && SHOW_DIFF) {
String diff = getDiffTool();
if (diff != null && ManagedFileAccess.file(diff).exists() || Utilities.isToken(diff)) {
@ -92,7 +136,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
private static String getDiffTool() throws IOException {
private String getDiffTool() throws IOException {
if (FhirSettings.hasDiffToolPath()) {
return FhirSettings.getDiffToolPath();
} else if (System.getenv("ProgramFiles") != null) {
@ -219,14 +263,12 @@ public class CompareUtilities extends BaseTestingUtilities {
return builder.parse(fn);
}
public static String checkJsonSrcIsSame(String id, String expected, String actual, JsonObject externals) throws FileNotFoundException, IOException {
return checkJsonSrcIsSame(id, expected, actual, true, externals);
public String checkJsonSrcIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
return checkJsonSrcIsSame(id, expected, actual, true);
}
public static String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff, JsonObject externals) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
self.externals = externals;
String result = self.compareJsonSrc(id, expectedString, actualString);
public String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
String result = compareJsonSrc(id, expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))
@ -259,9 +301,8 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
public static String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareJson(id, expected, actual);
public String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
String result = compareJson(id, expected, actual);
if (result != null && SHOW_DIFF) {
String diff = Utilities.path(System.getenv("ProgramFiles(X86)"), "WinMerge", "WinMergeU.exe");
List<String> command = new ArrayList<String>();
@ -294,16 +335,17 @@ public class CompareUtilities extends BaseTestingUtilities {
String n = en.getName();
if (!n.equals("fhir_comments")) {
if (expectedJsonObject.has(n)) {
String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n));
String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n), n, actualJsonObject);
if (!Utilities.noString(s))
return s;
} else
return "properties differ at " + path + ": missing property " + n;
} else if (!patternMode) {
return "properties differ at " + path + ": unexpected property " + n;
}
}
}
for (JsonProperty en : expectedJsonObject.getProperties()) {
String n = en.getName();
if (!n.equals("fhir_comments") && !n.equals("$optional$") && !optionals.contains(n)) {
if (!n.equals("fhir_comments") && !isOptional(n, optionals)) {
if (!actualJsonObject.has(n) && !allOptional(en.getValue()))
return "properties differ at " + path + ": missing property " + n;
}
@ -311,6 +353,10 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private boolean isOptional(String n, List<String> optionals) {
return n.equals("$optional$") || optionals.contains("*") || optionals.contains(n);
}
private boolean allOptional(JsonElement value) {
if (value.isJsonArray()) {
JsonArray a = value.asJsonArray();
@ -352,7 +398,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return res;
}
private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly) {
private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly, String name, JsonObject parent) {
if (!(expectedJsonElement instanceof JsonPrimitive && actualJsonElement instanceof JsonPrimitive)) {
if (actualJsonElement.getClass() != expectedJsonElement.getClass()) {
return createNotEqualMessage(id, "properties differ at " + path, expectedJsonElement.getClass().getName(), actualJsonElement.getClass().getName());
@ -394,30 +440,51 @@ public class CompareUtilities extends BaseTestingUtilities {
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
}
} else {
int expectedMin = countExpectedMin(expectedArray);
int oc = optionalCount(expectedArray);
int expectedMin = countExpectedMin(expectedArray, name, parent);
int oc = optionalCount(expectedArray, name, parent);
if (as > es || as < expectedMin)
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
int c = 0;
for (int i = 0; i < es; i++) {
if (c >= as) {
if (i >= es - oc && isOptional(expectedArray.get(i))) {
return null; // this is OK
} else {
return "One or more array items did not match at "+path+" starting at index "+i;
if (patternMode) {
int c = 0;
for (int i = 0; i < expectedArray.size(); i++) {
String s = "Doesn't exist";
CommaSeparatedStringBuilder cs = new CommaSeparatedStringBuilder("\r\n");
cs.append("");
while (s != null && c < actualArray.size()) {
s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null);
if (s != null) {
cs.append(" "+s);
}
c++;
}
if (s != null) {
return "The expected item at "+path+" at index "+i+" was not found: "+cs.toString();
}
}
String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false);
if (!Utilities.noString(s) && !isOptional(expectedArray.get(i))) {
return s;
} else {
if (as > es || as < expectedMin) {
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
}
if (Utilities.noString(s)) {
c++;
int c = 0;
for (int i = 0; i < es; i++) {
if (c >= as) {
if (i >= es - oc && isOptional(expectedArray.get(i), name, parent)) {
return null; // this is OK
} else {
return "One or more array items did not match at "+path+" starting at index "+i;
}
}
String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null);
if (!Utilities.noString(s) && !isOptional(expectedArray.get(i), name, parent)) {
return s;
}
if (Utilities.noString(s)) {
c++;
}
}
if (c < as) {
return "Unexpected Node found in array at '"+path+"' at index "+c;
}
}
if (c < as) {
return "Unexpected Node found in array at '"+path+"' at index "+c;
}
}
} else
@ -425,7 +492,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private int optionalCount(JsonArray arr) {
private int optionalCount(JsonArray arr, String name, JsonObject parent) {
int c = 0;
for (JsonElement e : arr) {
if (e.isJsonObject()) {
@ -438,14 +505,14 @@ public class CompareUtilities extends BaseTestingUtilities {
return c;
}
private boolean isOptional(JsonElement e) {
private boolean isOptional(JsonElement e, String name, JsonObject parent) {
return e.isJsonObject() && e.asJsonObject().has("$optional$");
}
private int countExpectedMin(JsonArray array) {
private int countExpectedMin(JsonArray array, String name, JsonObject parent) {
int count = array.size();
for (JsonElement e : array) {
if (isOptional(e)) {
if (isOptional(e, name, parent)) {
count--;
}
}
@ -485,8 +552,13 @@ public class CompareUtilities extends BaseTestingUtilities {
switch (expectedJsonString) {
case "$$" : return true;
case "$instant$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))");
case "$date$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?");
case "$uuid$": return actualJsonString.matches("urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
case "$string$": return actualJsonString.equals(actualJsonString.trim());
case "$id$": return actualJsonString.matches("[A-Za-z0-9\\-\\.]{1,64}");
case "$url$": return actualJsonString.matches("(https?://|www\\.)[-a-zA-Z0-9+&@#/%?=~_|!:.;]*[-a-zA-Z0-9+&@#/%=~_|]");
case "$token$": return actualJsonString.matches("[0-9a-zA-Z_][0-9a-zA-Z_\\.\\-]*");
case "$version$": return matchesVariable(actualJsonString, "version");
default:
throw new Error("Unhandled template: "+expectedJsonString);
}
@ -496,6 +568,14 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
private boolean matchesVariable(String value, String name) {
if (variables.containsKey(name)) {
return value.equals(variables.get(name));
} else {
return true;
}
}
private List<String> readChoices(String s) {
List<String> list = new ArrayList<>();
for (String p : s.split("\\|")) {
@ -504,13 +584,12 @@ public class CompareUtilities extends BaseTestingUtilities {
return list;
}
public static String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
public String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
return checkTextIsSame(id, expected, actual, true);
}
public static String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareText(id, expectedString, actualString);
public String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
String result = compareText(id, expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))

View File

@ -2700,7 +2700,7 @@ public class StructureMapUtilities {
private void addChildMappings(StringBuilder b, String id, String indent, StructureDefinition sd, ElementDefinition ed, boolean inner) throws DefinitionException {
boolean first = true;
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed).getList();
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed, true).getList();
for (ElementDefinition child : children) {
if (first && inner) {
b.append(" then {\r\n");

View File

@ -47,7 +47,7 @@ class LanguageUtilsTest implements ResourceLoaderTests {
.lines()
.collect(Collectors.joining("\n"));
String msg = CompareUtilities.checkJsonSrcIsSame("", generatedResource.toString(),text, null);
String msg = new CompareUtilities().checkJsonSrcIsSame("", generatedResource.toString(),text);
Assertions.assertNull(msg);
}

View File

@ -138,7 +138,7 @@ public class SQLOnFhirTests {
// sortResults(rows);
String expS = JsonParser.compose(exp, true);
String rowS = JsonParser.compose(rows, true);
String c = CompareUtilities.checkJsonSrcIsSame(name, expS, rowS, null);
String c = new CompareUtilities().checkJsonSrcIsSame(name, expS, rowS);
Assertions.assertNull(c, c);
} else if (test.testCase.has("expectCount")) {
Assertions.assertEquals(test.testCase.asInteger("expectCount"), results.size());

View File

@ -98,7 +98,7 @@ public class GraphQLEngineTests implements IGraphQLStorageServices {
IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", source), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", source)));
IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", output), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", output)));
TextFile.stringToFile(str.toString(), CompareUtilities.tempFile("graphql", output+".out"));
msg = CompareUtilities.checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out"));
msg = new CompareUtilities().checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out"));
Assertions.assertTrue(Utilities.noString(msg), msg);
}
else

View File

@ -279,7 +279,7 @@ public class NarrativeGenerationTests {
String actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".html");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
String msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName);
String msg = new CompareUtilities().checkXMLIsSame(id, expectedFileName, actualFileName);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
String disp = RendererFactory.factory(source, rc).buildSummary(ResourceWrapper.forResource(rc.getContextUtilities(), source));
@ -289,7 +289,7 @@ public class NarrativeGenerationTests {
actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".txt");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
msg = CompareUtilities.checkTextIsSame(id, expected, actual);
msg = new CompareUtilities().checkTextIsSame(id, expected, actual);
Assertions.assertTrue(msg == null, "Summary Output does not match expected: "+msg);
//

View File

@ -58,7 +58,7 @@ public class ParsingTests {
r = new XmlParser().parse(b);
b = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(r);
String output = new String(b);
String msg = CompareUtilities.checkJsonSrcIsSame(name, src, output, null);
String msg = new CompareUtilities().checkJsonSrcIsSame(name, src, output);
Assertions.assertTrue(msg == null, msg);
}

View File

@ -40,7 +40,7 @@ public class ResourceToElementTest {
Element e = p.parse(res);
new org.hl7.fhir.r5.elementmodel.XmlParser(ctxt).compose(e, ManagedFileAccess.outStream(src), OutputStyle.PRETTY, null);
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst), res);
String msg = CompareUtilities.checkXMLIsSame(filename, src, dst);
String msg = new CompareUtilities().checkXMLIsSame(filename, src, dst);
Assertions.assertNull(msg);
}

View File

@ -157,7 +157,7 @@ public class VocabTests {
String actualFileName = CompareUtilities.tempFile("vocab", test.getId() + ".actual.html");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
String msg = CompareUtilities.checkXMLIsSame(test.id, expectedFileName, actualFileName);
String msg = new CompareUtilities().checkXMLIsSame(test.id, expectedFileName, actualFileName);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
} else {
Assertions.fail("Expansion Failed: "+outcome.getError());

View File

@ -68,7 +68,7 @@ public class GeneratedPEModelTest {
Observation tgt = tp.build(ctxt);
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "pe-instance-gen.xml")), tgt);
String msg = CompareUtilities.checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml")));
String msg = new CompareUtilities().checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml")));
Assertions.assertNull(msg, msg);
}

View File

@ -422,7 +422,7 @@ public class PETests {
private void checkGeneratedJava(String name) throws FileNotFoundException, IOException {
String actual = Utilities.normalize(TextFile.fileToString(Utilities.path("[tmp]", "codegen", name+".java")));
String expected = Utilities.normalize(TestingUtilities.loadTestResource("r5", "profiles", name+".java"));
String msg = CompareUtilities.checkTextIsSame(name, expected, actual);
String msg = new CompareUtilities().checkTextIsSame(name, expected, actual);
if (msg != null) {
Assertions.fail("Generated code for "+name+" is different: "+msg);
}

View File

@ -59,7 +59,7 @@ public class CompareUtilitiesTests implements ResourceLoaderTests {
InputStream expectedXMLStream = classLoader.getResourceAsStream(expectedXMLPath);
InputStream actualXMLStream = classLoader.getResourceAsStream(actualXMLPath);
final String actualOutput = CompareUtilities.checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream);
final String actualOutput = new CompareUtilities().checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream);
if (expectedOutputFileName == null) {
assertNull(actualOutput);
@ -91,7 +91,7 @@ public class CompareUtilitiesTests implements ResourceLoaderTests {
final String expectedJSONPath = ROOT_JSON_TEST_PATH.resolve(expectedFileName).toString();
final String actualJSONPath = ROOT_JSON_TEST_PATH.resolve(actualFileName).toString();
final String actualOutput = CompareUtilities.checkJsonSrcIsSame(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false, null);
final String actualOutput = new CompareUtilities().checkJsonSrcIsSame(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false);
if (expectedOutputFileName == null) {
assertNull(actualOutput);
} else {

View File

@ -1 +1 @@
properties differ at : missing property unexpectedProperty
properties differ at : unexpected property unexpectedProperty

View File

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

View File

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

View File

@ -9,6 +9,7 @@ import org.hl7.fhir.utilities.settings.ServerDetailsPOJO;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -45,7 +46,7 @@ public class ManagedFhirWebAccessor extends ManagedWebAccessorBase<ManagedFhirWe
public ManagedFhirWebAccessor(String userAgent, List<ServerDetailsPOJO> serverAuthDetails) {
super(userAgent, serverAuthDetails);
super(Arrays.asList("fhir"), userAgent, serverAuthDetails);
this.timeout = 5000;
this.timeoutUnit = TimeUnit.MILLISECONDS;
}
@ -88,7 +89,7 @@ public class ManagedFhirWebAccessor extends ManagedWebAccessorBase<ManagedFhirWe
}
}
} else {
ServerDetailsPOJO settings = ManagedWebAccessUtils.getServer(httpRequest.getUrl().toString(), getServerAuthDetails());
ServerDetailsPOJO settings = ManagedWebAccessUtils.getServer(getServerTypes(), httpRequest.getUrl().toString(), getServerAuthDetails());
if (settings != null) {
switch (settings.getAuthenticationType()) {
case "basic":

View File

@ -52,9 +52,9 @@ import org.hl7.fhir.utilities.settings.ServerDetailsPOJO;
public class ManagedWebAccess {
public interface IWebAccessor {
HTTPResult get(String url, String accept, Map<String, String> headers) throws IOException;
HTTPResult post(String url, byte[] bytes, String contentType, String accept, Map<String, String> headers) throws IOException;
HTTPResult put(String url, byte[] bytes, String contentType, String accept, Map<String, String> headers) throws IOException;
HTTPResult get(Iterable<String> serverTypes, String url, String accept, Map<String, String> headers) throws IOException;
HTTPResult post(Iterable<String> serverTypes, String url, byte[] bytes, String contentType, String accept, Map<String, String> headers) throws IOException;
HTTPResult put(Iterable<String> serverTypes, String url, byte[] bytes, String contentType, String accept, Map<String, String> headers) throws IOException;
}
public interface IFhirWebAccessor {
@ -104,28 +104,28 @@ public class ManagedWebAccess {
ManagedWebAccess.userAgent = userAgent;
}
public static ManagedWebAccessor accessor() {
return new ManagedWebAccessor(userAgent, serverAuthDetails);
public static ManagedWebAccessor accessor(Iterable<String> serverTypes) {
return new ManagedWebAccessor(serverTypes, userAgent, serverAuthDetails);
}
public static ManagedFhirWebAccessor fhirAccessor() {
return new ManagedFhirWebAccessor(userAgent, serverAuthDetails);
}
public static HTTPResult get(String url) throws IOException {
return accessor().get(url);
public static HTTPResult get(Iterable<String> serverTypes, String url) throws IOException {
return accessor(serverTypes).get(url);
}
public static HTTPResult get(String url, String accept) throws IOException {
return accessor().get(url, accept);
public static HTTPResult get(Iterable<String> serverTypes, String url, String accept) throws IOException {
return accessor(serverTypes).get(url, accept);
}
public static HTTPResult post(String url, byte[] content, String contentType, String accept) throws IOException {
return accessor().post(url, content, contentType, accept);
public static HTTPResult post(Iterable<String> serverTypes, String url, byte[] content, String contentType, String accept) throws IOException {
return accessor(serverTypes).post(url, content, contentType, accept);
}
public static HTTPResult put(String url, byte[] content, String contentType, String accept) throws IOException {
return accessor().put(url, content, contentType, accept);
public static HTTPResult put(Iterable<String> serverTypes, String url, byte[] content, String contentType, String accept) throws IOException {
return accessor(serverTypes).put(url, content, contentType, accept);
}
public static HTTPResult httpCall(HTTPRequest httpRequest) throws IOException {
@ -136,15 +136,13 @@ public class ManagedWebAccess {
setAccessPolicy(FhirSettings.isProhibitNetworkAccess() ? WebAccessPolicy.PROHIBITED : WebAccessPolicy.DIRECT);
setUserAgent("hapi-fhir-tooling-client");
serverAuthDetails = new ArrayList<>();
serverAuthDetails.addAll(FhirSettings.getPackageServers());
serverAuthDetails.addAll(FhirSettings.getTerminologyServers());
serverAuthDetails.addAll(FhirSettings.getServers());
}
public static void loadFromFHIRSettings(FhirSettings settings) {
setAccessPolicy(settings.isProhibitNetworkAccess() ? WebAccessPolicy.PROHIBITED : WebAccessPolicy.DIRECT);
setUserAgent("hapi-fhir-tooling-client");
serverAuthDetails = new ArrayList<>();
serverAuthDetails.addAll(settings.getPackageServers());
serverAuthDetails.addAll(settings.getTerminologyServers());
serverAuthDetails.addAll(settings.getServers());
}
}

View File

@ -4,14 +4,21 @@ import org.hl7.fhir.utilities.settings.ServerDetailsPOJO;
public class ManagedWebAccessUtils {
public static ServerDetailsPOJO getServer(String url, Iterable<ServerDetailsPOJO> serverAuthDetails) {
public static ServerDetailsPOJO getServer(Iterable<String> serverTypes, String url, Iterable<ServerDetailsPOJO> serverAuthDetails) {
if (serverAuthDetails != null) {
for (ServerDetailsPOJO t : serverAuthDetails) {
if (url.startsWith(t.getUrl())) {
return t;
for (ServerDetailsPOJO serverDetails : serverAuthDetails) {
for (String serverType : serverTypes) {
if (url.startsWith(serverDetails.getUrl()) && typesMatch(serverType, serverDetails.getType())) {
return serverDetails;
}
}
}
}
return null;
}
private static boolean typesMatch(String criteria, String value) {
return criteria == null || value == null || criteria.equals(value);
}
}

View File

@ -14,8 +14,8 @@ import org.hl7.fhir.utilities.settings.ServerDetailsPOJO;
*/
public class ManagedWebAccessor extends ManagedWebAccessorBase<ManagedWebAccessor> {
public ManagedWebAccessor(String userAgent, List<ServerDetailsPOJO> serverAuthDetails) {
super(userAgent, serverAuthDetails);
public ManagedWebAccessor(Iterable<String> serverTypes, String userAgent, List<ServerDetailsPOJO> serverAuthDetails) {
super(serverTypes, userAgent, serverAuthDetails);
}
private Map<String, String> newHeaders() {
@ -66,7 +66,7 @@ public class ManagedWebAccessor extends ManagedWebAccessorBase<ManagedWebAccesso
}
}
} else {
ServerDetailsPOJO settings = ManagedWebAccessUtils.getServer(url, getServerAuthDetails());
ServerDetailsPOJO settings = ManagedWebAccessUtils.getServer(getServerTypes(), url, getServerAuthDetails());
if (settings != null) {
switch (settings.getAuthenticationType()) {
case "basic" :
@ -101,7 +101,7 @@ public class ManagedWebAccessor extends ManagedWebAccessorBase<ManagedWebAccesso
SimpleHTTPClient client = setupClient(url);
return client.get(url, accept);
case MANAGED:
return ManagedWebAccess.getAccessor().get(url, accept, newHeaders());
return ManagedWebAccess.getAccessor().get(getServerTypes(), url, accept, newHeaders());
case PROHIBITED:
throw new IOException("Access to the internet is not allowed by local security policy");
default:
@ -119,7 +119,7 @@ public class ManagedWebAccessor extends ManagedWebAccessorBase<ManagedWebAccesso
SimpleHTTPClient client = setupClient(url);
return client.post(url, contentType, content, accept);
case MANAGED:
return ManagedWebAccess.getAccessor().post(url, content, contentType, accept, newHeaders());
return ManagedWebAccess.getAccessor().post(getServerTypes(), url, content, contentType, accept, newHeaders());
case PROHIBITED:
throw new IOException("Access to the internet is not allowed by local security policy");
default:
@ -137,7 +137,7 @@ public class ManagedWebAccessor extends ManagedWebAccessorBase<ManagedWebAccesso
SimpleHTTPClient client = setupClient(url);
return client.put(url, contentType, content, accept);
case MANAGED:
return ManagedWebAccess.getAccessor().put(url, content, contentType, accept, newHeaders());
return ManagedWebAccess.getAccessor().put(getServerTypes(), url, content, contentType, accept, newHeaders());
case PROHIBITED:
throw new IOException("Access to the internet is not allowed by local security policy");
default:

View File

@ -8,6 +8,9 @@ import java.util.List;
import java.util.Map;
public abstract class ManagedWebAccessorBase<B extends ManagedWebAccessorBase<B>> {
@Getter
private final Iterable<String> serverTypes;
@Getter
private final String userAgent;
@Getter
@ -24,7 +27,8 @@ public abstract class ManagedWebAccessorBase<B extends ManagedWebAccessorBase<B>
@Getter
private final Map<String, String> headers = new HashMap<>();
public ManagedWebAccessorBase(String userAgent, List<ServerDetailsPOJO> serverAuthDetails) {
public ManagedWebAccessorBase(Iterable<String> serverTypes, String userAgent, List<ServerDetailsPOJO> serverAuthDetails) {
this.serverTypes = serverTypes;
this.userAgent = userAgent;
this.serverAuthDetails = serverAuthDetails;
}

View File

@ -589,6 +589,7 @@ public class I18nConstants {
public static final String SD_ELEMENT_FIXED_WRONG_TYPE = "SD_ELEMENT_FIXED_WRONG_TYPE";
public static final String SD_ELEMENT_NOT_IN_CONSTRAINT = "SD_ELEMENT_NOT_IN_CONSTRAINT";
public static final String SD_ELEMENT_PATTERN_WRONG_TYPE = "SD_ELEMENT_PATTERN_WRONG_TYPE";
public static final String SD_ELEMENT_PATTERN_NO_FIXED = "SD_ELEMENT_PATTERN_NO_FIXED";
public static final String SD_ELEMENT_REASON_DERIVED = "SD_ELEMENT_REASON_DERIVED";
public static final String SD_EXTENSION_URL_MISMATCH = "SD_EXTENSION_URL_MISMATCH";
public static final String SD_EXTENSION_URL_MISSING = "SD_EXTENSION_URL_MISSING";

View File

@ -2,34 +2,34 @@ package org.hl7.fhir.utilities.json;
import java.io.File;
/*
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.
*/
@ -37,6 +37,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.Stack;
@ -724,13 +725,13 @@ public class JsonTrackingParser {
}
public static JsonObject fetchJson(String source) throws IOException {
HTTPResult res = ManagedWebAccess.get(source+"?nocache=" + System.currentTimeMillis(), "application/json, application/fhir+json");
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source+"?nocache=" + System.currentTimeMillis(), "application/json, application/fhir+json");
res.checkThrowException();
return parseJson(res.getContent());
}
public static JsonArray fetchJsonArray(String source) throws IOException {
HTTPResult res = ManagedWebAccess.get(source+"?nocache=" + System.currentTimeMillis(), "application/json, application/fhir+json");
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"),source+"?nocache=" + System.currentTimeMillis(), "application/json, application/fhir+json");
res.checkThrowException();
return parseJsonArray(res.getContent());
}

View File

@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import org.hl7.fhir.utilities.TextFile;
@ -692,7 +693,7 @@ public class JsonParser {
private static byte[] fetch(String source) throws IOException {
String murl = source.contains("?") ? source+"&nocache=" + System.currentTimeMillis() : source+"?nocache=" + System.currentTimeMillis();
HTTPResult res = ManagedWebAccess.get(murl, "application/json, application/fhir+json");
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), murl, "application/json, application/fhir+json");
res.checkThrowException();
return res.getContent();
}

View File

@ -729,7 +729,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException {
try {
HTTPResult res = ManagedWebAccess.get(source);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source);
res.checkThrowException();
return new ByteArrayInputStream(res.getContent());
} catch (Exception e) {
@ -862,8 +862,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
}
private void loadFromBuildServer() throws IOException {
HTTPResult res = ManagedWebAccess.get("https://build.fhir.org/ig/qas.json?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), "https://build.fhir.org/ig/qas.json?nocache=" + System.currentTimeMillis());
res.checkThrowException();
buildInfo = (JsonArray) JsonParser.parse(TextFile.bytesToString(res.getContent()));

View File

@ -44,15 +44,7 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -1480,7 +1472,7 @@ public class NpmPackage {
}
public static NpmPackage fromUrl(String source) throws IOException {
HTTPResult res = ManagedWebAccess.get(source+"?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("npm-package", "fhir-package"), source+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return fromPackage(new ByteArrayInputStream(res.getContent()));
}

View File

@ -8,11 +8,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.*;
import javax.annotation.Nullable;
@ -175,11 +171,13 @@ public class PackageClient {
}
private InputStream fetchUrl(String source, String accept) throws IOException {
ManagedWebAccessor webAccessor = ManagedWebAccess.accessor();
ManagedWebAccessor webAccessor = ManagedWebAccess.accessor(Arrays.asList("web"));
if (server.getAuthenticationMode() == HTTPAuthenticationMode.TOKEN) {
webAccessor.withToken(server.getToken());
} else if (server.getAuthenticationMode() == HTTPAuthenticationMode.BASIC) {
webAccessor.withBasicAuth(server.getUsername(), server.getPassword());
} else if (server.getAuthenticationMode() == HTTPAuthenticationMode.APIKEY) {
webAccessor.withApiKey(server.getApiKey());
}
HTTPResult res = webAccessor.get(source, accept);
res.checkThrowException();

View File

@ -7,7 +7,6 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.hl7.fhir.utilities.http.HTTPAuthenticationMode;
import org.hl7.fhir.utilities.http.SimpleHTTPClient;
import org.hl7.fhir.utilities.settings.FhirSettings;
import org.hl7.fhir.utilities.settings.ServerDetailsPOJO;
@ -27,10 +26,11 @@ public class PackageServer {
serverType = PackageServerType.FHIR;
}
@Getter
private String url;
@Getter
private HTTPAuthenticationMode authenticationMode;
private HTTPAuthenticationMode authenticationMode;
@Getter
private PackageServerType serverType;
@ -43,9 +43,11 @@ public class PackageServer {
@Getter
private String token;
public String getUrl() {
return url;
}
@Getter
private String apiKey;
public static final String PRIMARY_SERVER = "https://packages.fhir.org";
public static final String SECONDARY_SERVER = "https://packages2.fhir.org/packages";
@ -69,24 +71,54 @@ public class PackageServer {
return new PackageServer(pojo.getUrl())
.withAuthenticationMode(getModeFromPOJO(pojo))
.withServerType(
pojo.getServerType() != null && pojo.getServerType().equalsIgnoreCase("npm") ? PackageServerType.NPM : PackageServerType.FHIR
getPackageServerType(pojo.getType())
)
.withUsername(pojo.getUsername())
.withPassword(pojo.getPassword())
.withToken(pojo.getToken());
.withToken(pojo.getToken())
.withApiKey(pojo.getApikey());
}
private static boolean isPackageServer(String serverType) {
if (serverType == null) {
return false;
}
if (serverType.equals("fhir-package")) {
return true;
}
if (serverType.equals("npm-package")) {
return true;
}
return false;
}
private static PackageServerType getPackageServerType(String serverType) {
if (serverType == null) {
return null;
}
if (serverType.equals("fhir-package")) {
return PackageServerType.FHIR;
}
if (serverType.equals("npm-package")) {
return PackageServerType.NPM;
}
return null;
}
@Nullable
private static HTTPAuthenticationMode getModeFromPOJO(ServerDetailsPOJO pojo) {
if (pojo.getAuthenticationType().equalsIgnoreCase("basic")) return HTTPAuthenticationMode.BASIC;
if (pojo.getAuthenticationType().equalsIgnoreCase("token")) return HTTPAuthenticationMode.TOKEN;
if (pojo.getAuthenticationType().equalsIgnoreCase("apikey")) return HTTPAuthenticationMode.APIKEY;
return null;
}
public static List<PackageServer> getConfiguredServers() {
return FhirSettings.getPackageServers().stream().map(
PackageServer::getPackageServerFromPOJO
).collect(Collectors.toList());
return FhirSettings.getServers().stream()
.filter(serverDetailsPOJO -> isPackageServer(serverDetailsPOJO.getType()))
.map(PackageServer::getPackageServerFromPOJO)
.collect(Collectors.toList());
}
@Override
@ -101,6 +133,7 @@ public class PackageServer {
packageServer.username = this.username;
packageServer.password = this.password;
packageServer.token = this.token;
packageServer.apiKey = this.apiKey;
return packageServer;
}
@ -133,4 +166,10 @@ public class PackageServer {
packageServer.token = token;
return packageServer;
}
public PackageServer withApiKey(String apiKey) {
PackageServer packageServer = this.copy();
packageServer.apiKey = apiKey;
return packageServer;
}
}

View File

@ -222,25 +222,17 @@ public class FhirSettings {
public static boolean isIgnoreDefaultPackageServers() {
getInstance();
if (instance.fhirSettings.getPackageManagement() == null || instance.fhirSettings.getPackageManagement().getIgnoreDefaultServers() == null) {
if (instance.fhirSettings.getIgnoreDefaultPackageServers() == null) {
return false;
}
return instance.fhirSettings.getPackageManagement().getIgnoreDefaultServers();
return instance.fhirSettings.getIgnoreDefaultPackageServers();
}
public static List<ServerDetailsPOJO> getPackageServers() {
public static List<ServerDetailsPOJO> getServers() {
getInstance();
if (instance.fhirSettings.getPackageManagement() == null) {
if (instance.fhirSettings.getServers() == null) {
return Collections.emptyList();
}
return Arrays.asList(instance.fhirSettings.getPackageManagement().getServers().toArray(new ServerDetailsPOJO[]{}));
}
public static List<ServerDetailsPOJO> getTerminologyServers() {
getInstance();
if (instance.fhirSettings.getTerminologyServers() == null) {
return Collections.emptyList();
}
return Arrays.asList(instance.fhirSettings.getTerminologyServers().getServers().toArray(new ServerDetailsPOJO[]{}));
return Arrays.asList(instance.fhirSettings.getServers().toArray(new ServerDetailsPOJO[]{}));
}
}

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.utilities.settings;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
@ -39,8 +41,9 @@ public class FhirSettingsPOJO {
private String txFhirDevelopment;
private String txFhirLocal;
private PackageManagementPOJO packageManagement;
private TerminologyServersPOJO terminologyServers;
private Boolean ignoreDefaultPackageServers;
private List<ServerDetailsPOJO> servers;
protected FhirSettingsPOJO() {
apiKeys = null;
@ -53,8 +56,6 @@ public class FhirSettingsPOJO {
txFhirProduction = TX_SERVER_PROD;
txFhirDevelopment = TX_SERVER_DEV;
txFhirLocal = TX_SERVER_LOCAL;
packageManagement = null;
terminologyServers = null;
servers = new ArrayList<>();
}
}

View File

@ -1,25 +0,0 @@
package org.hl7.fhir.utilities.settings;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.jackson.Jacksonized;
@Data
@Builder
@Jacksonized
@AllArgsConstructor
public class PackageManagementPOJO {
private Boolean ignoreDefaultServers;
private List<ServerDetailsPOJO> servers;
protected PackageManagementPOJO() {
ignoreDefaultServers = false;
servers = new ArrayList<>();
}
}

View File

@ -10,14 +10,25 @@ import lombok.extern.jackson.Jacksonized;
@Jacksonized
@AllArgsConstructor
public class ServerDetailsPOJO {
String url;
// possible values: none, basic, token, apikey
String authenticationType;
// npm or fhir, because the FHIR npm usage varies a little bit from general NPM usage (change over time)
String serverType;
/**
* This helps clients use appropriate API endpoints for each server type.
* <p/>
* It can be of the following types:
* <ul>
* <li>web</li>
* <li>fhir</li>
* <li>npm-package</li>
* <li>fhir-package</li>
* </ul>
*/
String type;
String username;

View File

@ -1,22 +0,0 @@
package org.hl7.fhir.utilities.settings;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.jackson.Jacksonized;
@Data
@Builder
@Jacksonized
@AllArgsConstructor
public class TerminologyServersPOJO {
private List<ServerDetailsPOJO> servers;
protected TerminologyServersPOJO() {
servers = new ArrayList<>();
}
}

View File

@ -593,7 +593,8 @@ SD_ED_TYPE_PROFILE_WRONG_TYPE_one = The type {0} is not in the list of allowed t
SD_ED_TYPE_PROFILE_WRONG_TYPE_other = The type {0} is not in the list of allowed types {1} in the profile {2}
SD_ELEMENT_FIXED_WRONG_TYPE = The base element has a fixed type of ''{0}'', so this element must have a fixed value of the same type, not ''{1}''
SD_ELEMENT_NOT_IN_CONSTRAINT = The element definition for {1} has a property {0} which is not allowed in a profile
SD_ELEMENT_PATTERN_WRONG_TYPE = The base element has a pattern type of ''{0}'', so this element must have a pattern value of the same type, not ''{1}''
SD_ELEMENT_PATTERN_WRONG_TYPE = The base element has a pattern type of ''{0}'', so this element must have a fixed value of the same type, not ''{1}''
SD_ELEMENT_PATTERN_NO_FIXED = The base element has a pattern type of ''{0}'', so this element must have a fixed value but it doesn''t
SD_ELEMENT_REASON_DERIVED = , because the value must match the fixed value define in ''{0}''
SD_EXTENSION_URL_MISMATCH = The fixed value for the extension URL is {1} which doesn''t match the canonical URL {0}
SD_EXTENSION_URL_MISSING = The value of Extension.url is not fixed to the extension URL {0}
@ -1152,7 +1153,7 @@ CODESYSTEM_CS_COMPLETE_AND_EMPTY = When a CodeSystem has content = ''complete'',
VALIDATION_VAL_VERSION_NOHASH = Version ''{0}'' contains a ''#'', which as this character is used in some URLs to separate the version and the fragment id. When version does include '#', systems will not be able to parse the URL
PRIMITIVE_TOO_SHORT = Value ''{0}'' is shorter than permitted minimum length of {1}
CANONICAL_MULTIPLE_VERSIONS_KNOWN = The version {2} for the {0} {1} is not known. These versions are known: {3}
SD_PATH_SLICING_DEPRECATED = The discriminator type ''{0}'' has been deprecated. Use type=fixed with a pattern[x] instead
SD_PATH_SLICING_DEPRECATED = The discriminator type ''{0}'' has been deprecated. Use type=value with a pattern[x] instead
SD_PATH_NOT_VALID = The discriminator path ''{0}'' does not appear to be valid for the element that is being sliced ''{1}''
SD_PATH_ERROR = The discriminator path ''{0}'' does not appear to be valid for the element that is being sliced ''{1}'': {2}

View File

@ -164,7 +164,7 @@ public class ManagedWebAccessAuthTests {
return new ServerDetailsPOJO(
server.url("").toString(),
"basic",
"dummyServerType",
"fhir",
DUMMY_USERNAME,
DUMMY_PASSWORD,
null, null);
@ -183,7 +183,7 @@ public void testTokenAuthFromSettings() throws IOException, InterruptedException
return new ServerDetailsPOJO(
server.url("").toString(),
"token",
"dummyServerType",
"fhir",
null,
null,
DUMMY_TOKEN, null);
@ -202,7 +202,7 @@ public void testTokenAuthFromSettings() throws IOException, InterruptedException
return new ServerDetailsPOJO(
server.url("").toString(),
"apikey",
"dummyServerType",
"fhir",
null,
null,
null, DUMMY_API_KEY);

View File

@ -85,19 +85,19 @@ public class FhirSettingsTests implements ResourceLoaderTests {
assertEquals("dummy-temp-path", fhirSettings.getTempPath());
assertEquals("dummy-test-igs-path", fhirSettings.getTestIgsPath());
assertTrue(fhirSettings.getPackageManagement().getIgnoreDefaultServers());
assertTrue(fhirSettings.getIgnoreDefaultPackageServers());
List<ServerDetailsPOJO> packageServers = fhirSettings.getPackageManagement().getServers();
List<ServerDetailsPOJO> servers = fhirSettings.getServers();
assertEquals(2, packageServers.size());
assertEquals(2, servers.size());
assertEquals("http://dummy.org", packageServers.get(0).url);
assertEquals("npm", packageServers.get(0).serverType);
assertEquals("joe", packageServers.get(0).username);
assertEquals("swordfish", packageServers.get(0).password);
assertEquals("BASIC", packageServers.get(0).authenticationType);
assertEquals("http://dummy.org", servers.get(0).url);
assertEquals("npm-package", servers.get(0).type);
assertEquals("joe", servers.get(0).username);
assertEquals("swordfish", servers.get(0).password);
assertEquals("BASIC", servers.get(0).authenticationType);
assertEquals("http://dummy2.com", packageServers.get(1).url);
assertEquals("http://dummy2.com", servers.get(1).url);
}
}

View File

@ -2,30 +2,28 @@
"apiKeys": {
"dummy-api-key": "dummy-api-key-value"
},
"npmPath": "dummy-npm-path",
"npmPath": "dummy-npm-path",
"rubyPath": "dummy-ruby-path",
"fhirTestCasesPath": "dummy-fhir-test-cases-path",
"diffToolPath": "dummy-diff-tool-path",
"tempPath": "dummy-temp-path",
"testIgsPath": "dummy-test-igs-path",
"unusedField" : "unused",
"packageManagement" : {
"ignoreDefaultServers" : true,
"servers": [
{
"url": "http://dummy.org",
"serverType": "npm",
"authenticationType": "BASIC",
"username": "joe",
"password": "swordfish"
},
{
"url": "http://dummy2.com",
"goobledy-goo": 5
}
]
},
"unusedData" : {
"unusedDateField" : "unused-data"
"unusedField": "unused",
"ignoreDefaultPackageServers": true,
"servers": [
{
"url": "http://dummy.org",
"type": "npm-package",
"authenticationType": "BASIC",
"username": "joe",
"password": "swordfish"
},
{
"url": "http://dummy2.com",
"goobledy-goo": 5
}
],
"unusedData": {
"unusedDateField": "unused-data"
}
}

View File

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

View File

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

View File

@ -430,7 +430,7 @@ public class IgLoader implements IValidationEngineLoader {
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException, IOException {
try {
HTTPResult res = ManagedWebAccess.get(source + "?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return new ByteArrayInputStream(res.getContent());
} catch (IOException e) {
@ -583,12 +583,12 @@ public class IgLoader implements IValidationEngineLoader {
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional, List<String> errors) throws FHIRException, IOException {
try {
try {
// try with cache-busting option and then try withhout in case the server doesn't support that
HTTPResult res = ManagedWebAccess.get(source + "?nocache=" + System.currentTimeMillis(), contentType);
// try with cache-busting option and then try without in case the server doesn't support that
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"),source + "?nocache=" + System.currentTimeMillis(), contentType);
res.checkThrowException();
return res.getContent();
} catch (Exception e) {
HTTPResult res = ManagedWebAccess.get(source, contentType);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source, contentType);
res.checkThrowException();
return res.getContent();
}

View File

@ -8,13 +8,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -319,7 +313,7 @@ public class Scanner {
}
protected void download(String address, String filename) throws IOException {
HTTPResult res = ManagedWebAccess.get(address);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), address);
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), filename);
}

View File

@ -19,7 +19,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.fhir.ucum.UcumEssenceService;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
@ -72,12 +71,9 @@ import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.AdditionalBindingPurpose;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.CodedContentValidationAction;
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
import org.hl7.fhir.r5.utils.validation.constants.CheckDisplayOption;
import org.hl7.fhir.r5.utils.validation.constants.CodedContentValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.IdStatus;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
@ -942,7 +938,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (output.startsWith("http://")) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
handleOutputToStream(r, output, bs, version);
HTTPResult res = ManagedWebAccess.post(output, bs.toByteArray(), "application/fhir+xml", "application/fhir+xml");
HTTPResult res = ManagedWebAccess.post(Arrays.asList("web"), output, bs.toByteArray(), "application/fhir+xml", "application/fhir+xml");
res.checkThrowException();
} else {
FileOutputStream s = ManagedFileAccess.outStream(output);
@ -1099,7 +1095,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
@Override
public byte[] fetchRaw(IResourceValidator validator, String source) throws IOException {
HTTPResult res = ManagedWebAccess.get(source);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source);
res.checkThrowException();
return res.getContent();
}

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.validation.cli.utils;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.TextFile;
@ -25,7 +26,7 @@ public class ProfileLoader {
private static byte[] loadProfileFromUrl(String src) throws FHIRException {
try {
HTTPResult res = ManagedWebAccess.get(src + "?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), src + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return res.getContent();
} catch (Exception e) {

View File

@ -6368,7 +6368,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
// get the list of direct defined children, including slices
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(profile, definition);
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(profile, definition, false);
if (childDefinitions.getList().isEmpty()) {
if (actualType == null) {
vi.setValid(false);
@ -6457,7 +6457,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_ACTUAL_TYPE_, actualType));
trackUsage(dt, valContext, element);
childDefinitions = profileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0));
childDefinitions = profileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0), false);
return childDefinitions;
}
@ -6998,7 +6998,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (ed.hasFixedCoding() && "http://loinc.org".equals(ed.getFixedCoding().getSystem())) {
return ed.getFixedCoding().getCode();
}
SourcedChildDefinitions children = profileUtilities.getChildMap(profile, ed);
SourcedChildDefinitions children = profileUtilities.getChildMap(profile, ed, true);
if (children != null) {
for (ElementDefinition t : children.getList()) {
if (t.getPath().endsWith(".code") && t.hasFixed()) {

View File

@ -503,9 +503,13 @@ public class StructureDefinitionValidator extends BaseValidator {
} else {
Element pattern = element.getNamedChild("pattern");
if (pattern != null) {
NodeStack fn = stack.push(pattern, 0, null, null);
if (rule(errors, "2024-03-26", IssueType.INVALID, fn, pattern.fhirType().equals(ed.getFixed().fhirType()), I18nConstants.SD_ELEMENT_PATTERN_WRONG_TYPE, pattern.fhirType(), ed.getFixed().fhirType())) {
ok = ((org.hl7.fhir.validation.instance.InstanceValidator) parent).checkFixedValue(errors, path, pattern, ed.getFixed(), base.getVersionedUrl(), "pattern", element, true, context.formatMessage(I18nConstants.SD_ELEMENT_REASON_DERIVED, base.getVersionedUrl())) && ok;
NodeStack fn = stack.push(pattern, 0, null, null);
if (rule(errors, "2024-03-26", IssueType.INVALID, fn, ed.hasFixed(), I18nConstants.SD_ELEMENT_PATTERN_NO_FIXED, pattern.fhirType())) {
if (rule(errors, "2024-03-26", IssueType.INVALID, fn, pattern.fhirType().equals(ed.getFixed().fhirType()), I18nConstants.SD_ELEMENT_PATTERN_WRONG_TYPE, pattern.fhirType(), ed.getFixed().fhirType())) {
ok = ((org.hl7.fhir.validation.instance.InstanceValidator) parent).checkFixedValue(errors, path, pattern, ed.getFixed(), base.getVersionedUrl(), "pattern", element, true, context.formatMessage(I18nConstants.SD_ELEMENT_REASON_DERIVED, base.getVersionedUrl())) && ok;
} else {
ok = false;
}
} else {
ok = false;
}

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.validation.ipa;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -160,7 +161,7 @@ public class IPAValidator {
private Element makeRequest(ValidationNode vn, String url) {
try {
HTTPResult result = ManagedWebAccess.get(url, "application/fhir+json");
HTTPResult result = ManagedWebAccess.get(Arrays.asList("web"), url, "application/fhir+json");
if (result.getCode() >= 300) {
vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "http.request",
"HTTP Return code is "+result.getCode()+" "+result.getMessage(),

View File

@ -108,7 +108,7 @@ public class TxServiceTestHelper {
writeDiffToFileSystem( name, expectedResponse, actualResponse);
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(actualResponse, fp);
@ -182,7 +182,7 @@ public class TxServiceTestHelper {
writeDiffToFileSystem(name, expectedResponse, actualResponse);
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(actualResponse, fp);

View File

@ -19,8 +19,10 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -30,11 +32,13 @@ import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r4b.context.TextClientLogger;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.test.utils.CompareUtilities;
@ -65,6 +69,8 @@ public class TxTester {
private JsonObject externals;
private String software;
private List<String> fails = new ArrayList<>();
private CapabilityStatement cstmt;
private TerminologyCapabilities tc;
public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) {
@ -107,14 +113,14 @@ public class TxTester {
json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone());
try {
JsonObject tests = loadTests();
ITerminologyClient tx = connectToServer(modes);
boolean ok = checkClient(tx);
tx = connectToServer(modes);
boolean ok = checkClient();
for (JsonObject suite : tests.getJsonObjects("suites")) {
if ((!suite.has("mode") || modes.contains(suite.asString("mode")))) {
if (suite.asBoolean("disabled")) {
// ok = true;
} else {
ok = runSuite(suite, tx, modes, filter, json.forceArray("suites")) && ok;
ok = runSuite(suite, modes, filter, json.forceArray("suites")) && ok;
}
}
}
@ -123,10 +129,10 @@ public class TxTester {
if (filter == null) {
String m = modes.isEmpty() ? "[none]" : CommaSeparatedStringBuilder.join(";", modes);
if (ok) {
System.out.println(software+" passed all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println(software+" passed all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
return true;
} else {
System.out.println(software+" did not pass all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println(software+" did not pass all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println("Failed Tests: "+ CommaSeparatedStringBuilder.join(",", fails ));
return false;
}
@ -153,12 +159,12 @@ public class TxTester {
return offset;
}
private boolean checkClient(ITerminologyClient tx) {
CapabilityStatement cstmt = tx.getCapabilitiesStatementQuick();
private boolean checkClient() {
cstmt = tx.getCapabilitiesStatement();
if (cstmt.hasSoftware()) {
software = cstmt.getSoftware().getName()+" v"+cstmt.getSoftware().getVersion();
}
tx.getTerminologyCapabilities();
tc = tx.getTerminologyCapabilities();
return true;
}
@ -171,7 +177,7 @@ public class TxTester {
return processHistoryMarkdown(loader.loadContent("history.md"));
}
private String processHistoryMarkdown(byte[] content) throws IOException {
public static String processHistoryMarkdown(byte[] content) throws IOException {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(content));
BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
@ -179,7 +185,7 @@ public class TxTester {
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
if (strLine.startsWith("## ")) {
return strLine.substring(3);
return strLine.substring(3).trim();
}
}
} finally {
@ -189,7 +195,7 @@ public class TxTester {
return "<1.6.0";
}
private ITerminologyClient connectToServer(List<String> modes) throws URISyntaxException {
private ITerminologyClient connectToServer(List<String> modes) throws URISyntaxException, IOException {
System.out.println("Connect to "+server);
software = server;
ITerminologyClient client = new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null);
@ -201,18 +207,18 @@ public class TxTester {
error = null;
if (tx == null) {
tx = connectToServer(modes);
checkClient(tx);
checkClient();
}
List<Resource> setup = loadSetupResources(suite);
if (runTest(suite, test, tx, setup, modes, "*", null)) {
if (runTest(suite, test, setup, modes, "*", null)) {
return null;
} else {
return error;
}
}
private boolean runSuite(JsonObject suite, ITerminologyClient tx, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
private boolean runSuite(JsonObject suite, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
System.out.println("Group "+suite.asString("name"));
JsonObject outputS = new JsonObject();
if (output != null) {
@ -226,14 +232,14 @@ public class TxTester {
if (test.asBoolean("disabled")) {
ok = true;
} else {
ok = runTest(suite, test, tx, setup, modes, filter, outputS.forceArray("tests")) && ok;
ok = runTest(suite, test, setup, modes, filter, outputS.forceArray("tests")) && ok;
}
}
}
return ok;
}
private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx, List<Resource> setup, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
private boolean runTest(JsonObject suite, JsonObject test, List<Resource> setup, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
JsonObject outputT = new JsonObject();
if (output != null) {
output.add(outputT);
@ -253,7 +259,8 @@ public class TxTester {
}
}
Parameters req = (Parameters) loader.loadResource(chooseParam(test, "request", modes));
String reqFile = chooseParam(test, "request", modes);
Parameters req = reqFile == null ? null : (Parameters) loader.loadResource(reqFile);
String fn = chooseParam(test, "response", modes);
String resp = TextFile.bytesToString(loader.loadContent(fn));
@ -266,16 +273,20 @@ public class TxTester {
String lang = test.asString("Content-Language");
String msg = null;
if (test.asString("operation").equals("expand")) {
msg = expand(test.str("name"), tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
if (test.asString("operation").equals("metadata")) {
msg = metadata(test.str("name"), setup, resp, fp, lang, profile, ext);
} else if (test.asString("operation").equals("term-caps")) {
msg = termcaps(test.str("name"), setup, resp, fp, lang, profile, ext);
} else if (test.asString("operation").equals("expand")) {
msg = expand(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("validate-code")) {
msg = validate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = validate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("cs-validate-code")) {
msg = validateCS(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = validateCS(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("lookup")) {
msg = lookup(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = lookup(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("translate")) {
msg = translate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = translate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else {
throw new Exception("Unknown Operation "+test.asString("operation"));
}
@ -311,6 +322,34 @@ public class TxTester {
}
}
private String metadata(String id, List<Resource> setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException {
CapabilityStatement cs = cstmt.copy();
TxTesterScrubbers.scrubCapStmt(cs, tight);
TxTesterSorters.sortCapStmt(cs);
String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs);
String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(csj, fp);
}
return diff;
}
private String termcaps(String id, List<Resource> setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException {
TerminologyCapabilities cs = tc.copy();
TxTesterScrubbers.scrubTermCaps(cs, tight);
TxTesterSorters.sortTermCaps(cs);
String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs);
String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(csj, fp);
}
return diff;
}
private String getResponseCode(JsonObject test) {
if (test.has("http-code")) {
return test.asString("http-code");
@ -340,7 +379,7 @@ public class TxTester {
return new URI(server).getHost();
}
private String lookup(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String lookup(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -363,7 +402,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -371,7 +410,7 @@ public class TxTester {
return diff;
}
private String translate(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String translate(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -394,7 +433,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -402,7 +441,7 @@ public class TxTester {
return diff;
}
private String expand(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String expand(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -425,7 +464,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, vsj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -444,7 +483,7 @@ public class TxTester {
}
}
private String validate(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String validate(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -468,7 +507,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -476,7 +515,7 @@ public class TxTester {
return diff;
}
private String validateCS(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String validateCS(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -499,7 +538,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -508,6 +547,13 @@ public class TxTester {
}
private Map<String, String> vars() {
Map<String, String> vars = new HashMap<String, String>();
vars.put("version", tx.getActualVersion().toCode());
return vars;
}
private List<Resource> loadSetupResources(JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException {
List<Resource> res = new ArrayList<>();
for (String s : suite.getStrings("setup")) {

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.validation.special;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Element;
import org.hl7.fhir.r5.model.Extension;
@ -7,6 +9,7 @@ import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.ElementVisitor;
import org.hl7.fhir.r5.utils.ElementVisitor.ElementVisitorInstruction;
@ -98,4 +101,12 @@ public class TxTesterScrubbers {
}
}
public static void scrubCapStmt(CapabilityStatement cs, boolean tight) {
// nothing yet?
}
public static void scrubTermCaps(TerminologyCapabilities cs, boolean tight) {
// nothing yet?
}
}

View File

@ -8,18 +8,34 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionFilterComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
import org.hl7.fhir.r5.model.Enumerations.CommonLanguages;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
@ -27,9 +43,11 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.validation.special.TxTesterSorters.CodeTypeSorter;
public class TxTesterSorters {
public static void main(String[] args) throws JsonException, IOException {
Resource r = new JsonParser().parse(new FileInputStream(args[0]));
switch (r.fhirType()) {
@ -234,7 +252,205 @@ public class TxTesterSorters {
}
}
public static void sortCapStmt(CapabilityStatement cs) {
Collections.sort(cs.getFormat(), new CodeTypeSorter());
Collections.sort(cs.getInstantiates(), new CanonicalTypeSorter());
Collections.sort(cs.getImports(), new CanonicalTypeSorter());
Collections.sort(cs.getAcceptLanguage(), new CodeTypeSorter());
Collections.sort(cs.getRest(), new CSRestSorter());
for (CapabilityStatementRestComponent r : cs.getRest()) {
if (r.hasSecurity()) {
for (CodeableConcept cc : r.getSecurity().getService()) {
Collections.sort(cc.getCoding(), new CodingSorter());
}
Collections.sort(r.getSecurity().getService(), new CodeableConceptSorter());
}
Collections.sort(r.getResource(), new CSRestResourceSorter());
for (CapabilityStatementRestResourceComponent res : r.getResource()) {
Collections.sort(res.getSupportedProfile(), new CanonicalTypeSorter());
Collections.sort(res.getInteraction(), new CSRestResourceInteractionSorter());
Collections.sort(res.getSearchInclude(), new StringTypeSorter());
Collections.sort(res.getSearchRevInclude(), new StringTypeSorter());
Collections.sort(res.getSearchParam(), new SearchParamSorter());
Collections.sort(res.getOperation(), new CSRestResourceOperationSorter());
}
Collections.sort(r.getInteraction(), new CSRestInteractionSorter());
Collections.sort(r.getSearchParam(), new SearchParamSorter());
Collections.sort(r.getOperation(), new CSRestResourceOperationSorter());
Collections.sort(r.getCompartment(), new CanonicalTypeSorter());
}
}
public static class CodeTypeSorter implements Comparator<CodeType> {
@Override
public int compare(CodeType o1, CodeType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class StringTypeSorter implements Comparator<StringType> {
@Override
public int compare(StringType o1, StringType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class CanonicalTypeSorter implements Comparator<CanonicalType> {
@Override
public int compare(CanonicalType o1, CanonicalType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class CodingSorter implements Comparator<Coding> {
@Override
public int compare(Coding c1, Coding c2) {
if (c1.getSystem().equals(c2.getSystem())) {
return c1.getCode().compareTo(c2.getCode());
} else {
return c1.getSystem().compareTo(c2.getSystem());
}
}
}
public static class CodeableConceptSorter implements Comparator<CodeableConcept> {
@Override
public int compare(CodeableConcept o1, CodeableConcept o2) {
if (o1.hasCoding() && o2.hasCoding()) {
Coding c1 = o1.getCodingFirstRep();
Coding c2 = o2.getCodingFirstRep();
if (c1.getSystem().equals(c2.getSystem())) {
return c1.getCode().compareTo(c2.getCode());
} else {
return c1.getSystem().compareTo(c2.getSystem());
}
} else {
return o1.getText().compareTo(o2.getText());
}
}
}
public static class CSRestSorter implements Comparator<CapabilityStatementRestComponent> {
@Override
public int compare(CapabilityStatementRestComponent o1, CapabilityStatementRestComponent o2) {
return o1.getMode().compareTo(o2.getMode());
}
}
public static class CSRestResourceSorter implements Comparator<CapabilityStatementRestResourceComponent> {
@Override
public int compare(CapabilityStatementRestResourceComponent o1, CapabilityStatementRestResourceComponent o2) {
return o1.getType().compareTo(o2.getType());
}
}
public static class CSRestResourceInteractionSorter implements Comparator<ResourceInteractionComponent> {
@Override
public int compare(ResourceInteractionComponent o1, ResourceInteractionComponent o2) {
return o1.getCode().toCode().compareTo(o2.getCode().toCode());
}
}
public static class CSRestInteractionSorter implements Comparator<SystemInteractionComponent> {
@Override
public int compare(SystemInteractionComponent o1, SystemInteractionComponent o2) {
return o1.getCode().compareTo(o2.getCode());
}
}
public static class SearchParamSorter implements Comparator<CapabilityStatementRestResourceSearchParamComponent> {
@Override
public int compare(CapabilityStatementRestResourceSearchParamComponent o1, CapabilityStatementRestResourceSearchParamComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
public static class CSRestResourceOperationSorter implements Comparator<CapabilityStatementRestResourceOperationComponent> {
@Override
public int compare(CapabilityStatementRestResourceOperationComponent o1, CapabilityStatementRestResourceOperationComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
public static void sortTermCaps(TerminologyCapabilities tc) {
Collections.sort(tc.getCodeSystem(), new TCCodeSystemSorter());
for (TerminologyCapabilitiesCodeSystemComponent t : tc.getCodeSystem()) {
Collections.sort(t.getVersion(), new TCCodeSystemVersionSorter());
for (TerminologyCapabilitiesCodeSystemVersionComponent v : t.getVersion()) {
Collections.sort(v.getLanguage(), new LanguageSorter());
Collections.sort(v.getProperty(), new CodeTypeSorter());
Collections.sort(v.getFilter(), new TCCodeSystemVersionFilterSorter());
}
}
Collections.sort(tc.getExpansion().getParameter(), new TCExpansionParameterSorter());
}
public static class LanguageSorter implements Comparator<Enumeration<CommonLanguages>> {
@Override
public int compare(Enumeration<CommonLanguages> o1, Enumeration<CommonLanguages> o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class TCCodeSystemSorter implements Comparator<TerminologyCapabilitiesCodeSystemComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemComponent o1, TerminologyCapabilitiesCodeSystemComponent o2) {
return o1.getUri().compareTo(o2.getUri());
}
}
public static class TCCodeSystemVersionSorter implements Comparator<TerminologyCapabilitiesCodeSystemVersionComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemVersionComponent o1, TerminologyCapabilitiesCodeSystemVersionComponent o2) {
return o1.getCode() == null || o2.getCode() == null ? 0 : o1.getCode().compareTo(o2.getCode());
}
}
public static class TCCodeSystemVersionFilterSorter implements Comparator<TerminologyCapabilitiesCodeSystemVersionFilterComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemVersionFilterComponent o1, TerminologyCapabilitiesCodeSystemVersionFilterComponent o2) {
return o1.getCode().compareTo(o2.getCode());
}
}
public static class TCExpansionParameterSorter implements Comparator<TerminologyCapabilitiesExpansionParameterComponent> {
@Override
public int compare(TerminologyCapabilitiesExpansionParameterComponent o1, TerminologyCapabilitiesExpansionParameterComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
}

View File

@ -245,7 +245,7 @@ public class ComparisonTests {
String en = Utilities.path("[tmp]", "comparison", Utilities.changeFileExt(name, ".expected.html"));
TextFile.stringToFile(expected, en);
String msg = CompareUtilities.checkXMLIsSame(id, en, an);
String msg = new CompareUtilities().checkXMLIsSame(id, en, an);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
}

View File

@ -20,7 +20,9 @@ import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtil;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.settings.FhirSettings;
import org.hl7.fhir.utilities.tests.TestConfig;
@ -81,6 +83,7 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
for (String id : names) {
objects.add(new Object[]{id, examples.get(id)});
}
objects.add(new Object[]{"final", null});
return objects;
}
@ -90,6 +93,7 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
private String version = "5.0.0";
private static TxTester tester;
private List<String> modes = new ArrayList<>();
private boolean error = false;
public LocalTerminologyServiceTests(String name, JsonObjectPair setup) {
this.setup = setup;
@ -107,19 +111,33 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
logTestSkip("No local terminology server available.");
return;
}
if (SERVER != null) {
if (tester == null) {
tester = new TxTester(this, SERVER, true, externals);
if (setup == null) {
if (!error) {
System.out.println("tx.fhir.org passed all HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
}
String err = tester.executeTest(setup.suite, setup.test, modes);
Assertions.assertTrue(err == null, err);
Assertions.assertTrue(!error);
} else {
Assertions.assertTrue(true);
if (SERVER != null) {
if (tester == null) {
tester = new TxTester(this, SERVER, true, externals);
}
String err = tester.executeTest(setup.suite, setup.test, modes);
error = error || err != null;
Assertions.assertTrue(err == null, err);
} else {
Assertions.assertTrue(true);
}
}
}
private String loadVersion() throws JsonException, IOException {
return TxTester.processHistoryMarkdown(TestingUtilities.loadTestResourceBytes("tx", "history.md"));
}
private void logTestSkip(String reason) {
System.out.println("Skipping test: " + setup.suite.asString("name") + " " + setup.test.asString("name") + " reason: " + reason);
if (setup != null) {
System.out.println("Skipping test: " + setup.suite.asString("name") + " " + setup.test.asString("name") + " reason: " + reason);
}
}
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {

View File

@ -92,7 +92,8 @@ private static TxTestData testData;
if (setup.getSuite().asBoolean("disabled") || setup.getTest().asBoolean("disabled")) {
return;
}
Resource req = loadResource(setup.getTest().asString("request"));
String reqFile = setup.getTest().asString("request");
Resource req = reqFile == null ? null : loadResource(reqFile);
String fn = setup.getTest().has("response:tx.fhir.org") ? setup.getTest().asString("response:tx.fhir.org") : setup.getTest().asString("response");
String resp = TestingUtilities.loadTestResource("tx", fn);
String fp = Utilities.path("[tmp]", "tx", fn);
@ -114,7 +115,7 @@ private static TxTestData testData;
} else if (setup.getTest().asString("operation").equals("cs-validate-code")) {
String diff = TxServiceTestHelper.getDiffForValidation(setup.getTest().str("name"), engine.getContext(), setup.getTest().asString("name"), req, resp, setup.getTest().asString("Content-Language"), fp, ext, true);
assertNull(diff, diff);
} else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate")) {
} else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate", "metadata", "term-caps")) {
Assertions.assertTrue(true); // we don't test these for the internal server
} else {
Assertions.fail("Unknown Operation "+ setup.getTest().asString("operation"));
@ -140,7 +141,7 @@ private static TxTestData testData;
TxTesterSorters.sortValueSet(vse.getValueset());
TxTesterScrubbers.scrubVS(vse.getValueset(), false);
String vsj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(vse.getValueset());
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, ext);
String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, vsj);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -189,7 +190,7 @@ private static TxTestData testData;
TxTesterScrubbers.scrubOO(oo, false);
String ooj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, ooj, ext);
String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, ooj);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(ooj, fp);

View File

@ -121,11 +121,11 @@ public class StructureMappingTests {
fail(e.getMessage());
}
if (output.endsWith("json")) {
msg = CompareUtilities.checkJsonSrcIsSame(name, s.toString(), outputJson, null);
msg = new CompareUtilities().checkJsonSrcIsSame(name, s.toString(), outputJson);
} else {
TextFile.bytesToFile(s.toByteArray(), fileOutputRes);
TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig);
msg = CompareUtilities.checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes));
msg = new CompareUtilities().checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes));
}
if (!Utilities.noString(msg)) {
System.out.print(s.toString());

View File

@ -8,17 +8,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.NotImplementedException;
@ -858,7 +849,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
@Override
public byte[] fetchRaw(IResourceValidator validator, String source) throws MalformedURLException, IOException {
HTTPResult res = ManagedWebAccess.get(source);
HTTPResult res = ManagedWebAccess.get(Arrays.asList("web"), source);
res.checkThrowException();
return res.getContent();
}

View File

@ -14,7 +14,7 @@
HAPI FHIR
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.4.1-SNAPSHOT</version>
<version>6.4.2-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
@ -23,7 +23,7 @@
<commons_io_version>2.17.0</commons_io_version>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.6.1-SNAPSHOT</validator_test_case_version>
<validator_test_case_version>1.6.6-SNAPSHOT</validator_test_case_version>
<jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>