diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java index 13fb36c81c..d88678fd5e 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java @@ -126,7 +126,7 @@ private void process(String source, String dest, boolean onlyNew, boolean onlyAc } private void cleanValueSets(List allOids, String dest) throws IOException { - cleanValueSets(allOids, new File(Utilities.path(dest))); + cleanValueSets(allOids, ManagedFileAccess.file(Utilities.path(dest))); } private void cleanValueSets(List allOids, File file) { diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java index e6ba510b02..6efce79ec9 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java @@ -265,4 +265,10 @@ public Parameters translate(Parameters params) throws FHIRException { return (Parameters) VersionConvertorFactory_10_50.convertResource(client.translate((org.hl7.fhir.dstu2.model.Parameters) VersionConvertorFactory_10_50.convertResource(params))); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java index de07084d64..8856067a26 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java @@ -268,4 +268,10 @@ public Parameters translate(Parameters params) throws FHIRException { return (Parameters) VersionConvertorFactory_30_50.convertResource(client.transform((org.hl7.fhir.dstu3.model.Parameters) VersionConvertorFactory_30_50.convertResource(params))); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java index b4aaa69f09..bfcd9267dd 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java @@ -11,6 +11,8 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.utils.client.EFhirClientException; import org.hl7.fhir.r4.utils.client.FHIRToolingClient; +import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CapabilityStatement; @@ -28,9 +30,10 @@ public class TerminologyClientR4 implements ITerminologyClient { - private final FHIRToolingClient client; // todo: use the R2 client + private final FHIRToolingClient client; private ClientHeaders clientHeaders; private String id; + private ITerminologyConversionLogger logger; public TerminologyClientR4(String id, String address, String userAgent) throws URISyntaxException { this.client = new FHIRToolingClient(address, userAgent); @@ -71,7 +74,7 @@ public FhirPublication getActualVersion() { @Override public TerminologyCapabilities getTerminologyCapabilities() throws FHIRException { - return (TerminologyCapabilities) VersionConvertorFactory_40_50.convertResource(client.getTerminologyCapabilities()); + return (TerminologyCapabilities) convertResource("getTerminologyCapabilities.response", client.getTerminologyCapabilities()); } @Override @@ -81,29 +84,30 @@ public String getAddress() { @Override public ValueSet expandValueset(ValueSet vs, Parameters p) throws FHIRException { - org.hl7.fhir.r4.model.ValueSet vs2 = vs == null ? null : (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(vs); - org.hl7.fhir.r4.model.Parameters p2 = p == null ? null : (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(p); + org.hl7.fhir.r4.model.ValueSet vs2 = vs == null ? null : (org.hl7.fhir.r4.model.ValueSet) convertResource("expandValueset.valueset", vs); + org.hl7.fhir.r4.model.Parameters p2 = p == null ? null : (org.hl7.fhir.r4.model.Parameters) convertResource("expandValueset.parameters", p); try { vs2 = client.expandValueset(vs2, p2); // todo: second parameter - return (ValueSet) VersionConvertorFactory_40_50.convertResource(vs2); + return (ValueSet) convertResource("expandValueset.response", vs2); } catch (org.hl7.fhir.r4.utils.client.EFhirClientException e) { if (e.getServerErrors().size() > 0) { - throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), (org.hl7.fhir.r5.model.OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0))); + throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), (org.hl7.fhir.r5.model.OperationOutcome) convertResource("expandValueset.error", e.getServerErrors().get(0))); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage()); } } } + @Override public Parameters validateCS(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateCS.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "validate-code", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("validateCS.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("validateCS.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -117,12 +121,12 @@ public Parameters validateCS(Parameters pin) throws FHIRException { @Override public Parameters subsumes(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("subsumes.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "subsumes", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("subsumes.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("subsumes.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -135,12 +139,12 @@ public Parameters subsumes(Parameters pin) throws FHIRException { @Override public Parameters validateVS(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateVS.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("validateVS.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -175,22 +179,22 @@ public ITerminologyClient setRetryCount(int retryCount) throws FHIRException { @Override public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException { - return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatementQuick()); + return (CapabilityStatement) convertResource("getCapabilitiesStatementQuick.response", client.getCapabilitiesStatementQuick()); } @Override public CapabilityStatement getCapabilitiesStatement() throws FHIRException { - return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatement()); + return (CapabilityStatement) convertResource("getCapabilitiesStatement.response", client.getCapabilitiesStatement()); } @Override public Parameters lookupCode(Map params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params)); + return (Parameters) convertResource("lookupCode.response", client.lookupCode(params)); } @Override public Parameters lookupCode(Parameters params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params))); + return (Parameters) convertResource("lookupCode.response", client.lookupCode((org.hl7.fhir.r4.model.Parameters) convertResource("lookupCode.request", params))); } @Override @@ -200,8 +204,8 @@ public int getRetryCount() throws FHIRException { @Override public Bundle validateBatch(Bundle batch) { - org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) VersionConvertorFactory_40_50.convertResource(batch)); - return result == null ? null : (Bundle) VersionConvertorFactory_40_50.convertResource(result); + org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) convertResource("validateBatch.request", batch)); + return result == null ? null : (Bundle) convertResource("validateBatch.response", result); } @Override @@ -216,7 +220,7 @@ public CanonicalResource read(String type, String id) { if (r4 == null) { throw new FHIRException("Unable to fetch resource " + Utilities.pathURL(getAddress(), type, id)); } - org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4); + org.hl7.fhir.r5.model.Resource r5 = convertResource("read.result", r4); if (r5 == null) { throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 (internal representation)"); } @@ -278,12 +282,55 @@ public int getUseCount() { @Override public Bundle search(String type, String criteria) { org.hl7.fhir.r4.model.Bundle result = client.search(type, criteria); - return result == null ? null : (Bundle) VersionConvertorFactory_40_50.convertResource(result); + return result == null ? null : (Bundle) convertResource("search.result", result); } @Override public Parameters translate(Parameters params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.translate((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params))); + return (Parameters) convertResource("translate.response", client.translate((org.hl7.fhir.r4.model.Parameters) convertResource("translate.request", params))); + } + + private org.hl7.fhir.r4.model.Resource convertResource(String name, org.hl7.fhir.r5.model.Resource resource) { + if (logger != null) { + try { + logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(resource)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + org.hl7.fhir.r4.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); + if (logger != null) { + try { + logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(res)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + return res; + } + + private org.hl7.fhir.r5.model.Resource convertResource(String name, org.hl7.fhir.r4.model.Resource resource) { + if (logger != null && name != null) { + try { + logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(resource)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + org.hl7.fhir.r5.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); + if (logger != null && name != null) { + try { + logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(res)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + return res; + } + + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + this.logger = logger; } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java index 168718ca58..0aee757561 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java @@ -420,7 +420,7 @@ public void renderTable(RenderingStatus status, ResourceWrapper res, List columns, List list) if (actor == null) { columns.add(new Column(col, tail(col), context.formatPhrase(RenderingContext.STRUC_DEF_UNDEF_ACT, col, col)+" ")); } else { - columns.add(new Column(col, actor.getName(), context.formatPhrase(RenderingContext.STRUC_DEF_ACT, actor.present(), actor.getWebPath())+" ")); + columns.add(new Column(col, actor.present(), context.formatPhrase(RenderingContext.STRUC_DEF_ACT, actor.present(), actor.getWebPath())+" ")); } } } @@ -1761,7 +1761,6 @@ else if (definition.hasBinding()) obr.seeObligations(profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)); } obr.renderTable(status, res, gen, c, inScopeElements); - if (definition.hasMaxLength() && definition.getMaxLength()!=0) { if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH), null).addStyle("font-weight:bold"))); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java index fec587dce8..0cddd0e98e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java @@ -76,4 +76,10 @@ public interface ITerminologyClient { String getUserAgent(); int getUseCount(); Bundle search(String type, String criteria); + + // internal conversion logging + public interface ITerminologyConversionLogger { + void log(String name, String resourceType, String version, byte[] cnt); + } + void setConversionLogger(ITerminologyConversionLogger logger); } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java index 9946c583bb..a3baf66fbe 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java @@ -275,5 +275,11 @@ public Parameters translate(Parameters params) throws FHIRException { return client.translate(params); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/TestDataFactory.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/TestDataFactory.java index 8ae3b3f7be..0ccfdcc081 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/TestDataFactory.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/TestDataFactory.java @@ -39,6 +39,7 @@ import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.utilities.http.HTTPResult; import org.hl7.fhir.utilities.http.ManagedWebAccess; import org.hl7.fhir.utilities.json.JsonException; @@ -297,8 +298,8 @@ private void executeProfile() throws IOException { } private void checkDownloadBaseData() throws IOException { - localData = new File(Utilities.path("[tmp]", "fhir-test-data.db")); - File localInfo = new File(Utilities.path("[tmp]", "fhir-test-data.json")); + localData = ManagedFileAccess.file(Utilities.path("[tmp]", "fhir-test-data.db")); + File localInfo = ManagedFileAccess.file(Utilities.path("[tmp]", "fhir-test-data.json")); try { JsonObject local = localInfo.exists() ? JsonParser.parseObject(localInfo) : null; JsonObject json = JsonParser.parseObjectFromUrl("http://fhir.org/downloads/test-data-versions.json"); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/dataprovider/ExcelDataProvider.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/dataprovider/ExcelDataProvider.java index 9a536c8a46..a333c4891f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/dataprovider/ExcelDataProvider.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/testfactory/dataprovider/ExcelDataProvider.java @@ -3,6 +3,7 @@ import org.apache.poi.ss.usermodel.*; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; @@ -37,7 +38,7 @@ public class ExcelDataProvider extends TableDataProvider { * @throws InvalidFormatException If the file format is invalid. */ public ExcelDataProvider(String filename, String sheetName) throws IOException, InvalidFormatException { - FileInputStream fis = new FileInputStream(new File(filename)); + FileInputStream fis = new FileInputStream(ManagedFileAccess.file(filename)); this.workbook = WorkbookFactory.create(fis); if (sheetName != null) { this.sheet = workbook.getSheet(sheetName); @@ -60,7 +61,7 @@ public ExcelDataProvider(String filename, String sheetName) throws IOException, public ExcelDataProvider(String filename) throws InvalidFormatException, IOException { - FileInputStream fis = new FileInputStream(new File(filename)); + FileInputStream fis = new FileInputStream(ManagedFileAccess.file(filename)); this.workbook = WorkbookFactory.create(fis); this.sheet = workbook.getSheetAt(0); loadColumnHeaders(); diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index d9baeb9314..d3efecee46 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -477,6 +477,11 @@ public static File createDirectory(String path) throws IOException { return ManagedFileAccess.file(path); } + public static File createDirectoryNC(String path) throws IOException { + ManagedFileAccess.file(path).mkdirs(); + return ManagedFileAccess.file(path); + } + public static String changeFileExt(String name, String ext) { if (name.lastIndexOf('.') > -1) return name.substring(0, name.lastIndexOf('.')) + ext; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java index 668b9de08f..baba2e4a1a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java @@ -325,7 +325,7 @@ private void generate(String source, String src, String dest, String tgt, int co // save the destination file String fn = Utilities.path(source, "source", dest); List objects; - if (new File(fn).exists()) { + if (ManagedFileAccess.file(fn).exists()) { objects = loadPOFile(fn); } else { objects = new ArrayList(); diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java index c64b6d0e27..31ee4859eb 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java @@ -35,6 +35,18 @@ public JsonObject add(String name, JsonElement value) throws JsonException { propMap.put(name, p); return this; } + + public JsonObject add(int index, String name, JsonElement value) throws JsonException { + check(name != null, "Json Property Name is null"); + check(value != null, "Json Property Value is null"); + if (get(name) != null) { + check(false, "Name '"+name+"' already exists (value = "+get(name).toString()+")"); + } + JsonProperty p = new JsonProperty(name, value); + properties.add(index, p); + propMap.put(name, p); + return this; + } public JsonObject addIfNotNull(String name, JsonElement value) throws JsonException { if (value != null) { @@ -347,6 +359,16 @@ public JsonArray forceArray(String name) throws JsonException { } return getJsonArray(name); } + + public JsonArray forceArray(int index, String name) throws JsonException { + if (has(name) && !hasArray(name)) { + remove(name); + } + if (!has(name)) { + add(index, name, new JsonArray()); + } + return getJsonArray(name); + } public List getJsonObjects(String name) { List res = new ArrayList<>(); diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManagerLocks.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManagerLocks.java index a1b4f4e0ea..27c45a34be 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManagerLocks.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManagerLocks.java @@ -284,7 +284,7 @@ public T doWriteWithLock(FilesystemPackageCacheManager.CacheLockFunction } public synchronized PackageLock getPackageLock(String packageName) throws IOException { - File lockFile = new File(Utilities.path(cacheFolder.getAbsolutePath(), packageName + ".lock")); + File lockFile = ManagedFileAccess.file(Utilities.path(cacheFolder.getAbsolutePath(), packageName + ".lock")); return packageLocks.computeIfAbsent(lockFile, (k) -> new PackageLock(k, new ReentrantReadWriteLock())); } } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java index e075c9b2c5..d46cd1c1db 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java @@ -31,7 +31,7 @@ public class PackageHacker { private static boolean useSecureReferences = false; public static void main(String[] args) throws FileNotFoundException, IOException { -// new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir")); +// new PackageHacker().massEdit(ManagedFileAccess.file("/Users/grahamegrieve/web/hl7.org/fhir")); // new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz"); // new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz"); // new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz"); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java index db282ac8aa..540276a226 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java @@ -643,9 +643,9 @@ protected ValidationEngine buildValidationEngine(CliContext cliContext, String d } if (cliContext.getAdvisorFile() != null) { if (cliContext.getAdvisorFile().endsWith(".json")) { - validationEngine.getPolicyAdvisor().setPolicyAdvisor(new JsonDrivenPolicyAdvisor(validationEngine.getPolicyAdvisor().getPolicyAdvisor(), new File(cliContext.getAdvisorFile()))); + validationEngine.getPolicyAdvisor().setPolicyAdvisor(new JsonDrivenPolicyAdvisor(validationEngine.getPolicyAdvisor().getPolicyAdvisor(), ManagedFileAccess.file(cliContext.getAdvisorFile()))); } else { - validationEngine.getPolicyAdvisor().setPolicyAdvisor(new TextDrivenPolicyAdvisor(validationEngine.getPolicyAdvisor().getPolicyAdvisor(), new File(cliContext.getAdvisorFile()))); + validationEngine.getPolicyAdvisor().setPolicyAdvisor(new TextDrivenPolicyAdvisor(validationEngine.getPolicyAdvisor().getPolicyAdvisor(), ManagedFileAccess.file(cliContext.getAdvisorFile()))); } } else { validationEngine.getPolicyAdvisor().setPolicyAdvisor(new BasePolicyAdvisorForFullValidation(validationEngine.getPolicyAdvisor() == null ? refpol : validationEngine.getPolicyAdvisor().getReferencePolicy())); @@ -929,7 +929,7 @@ public void instanceFactory(CliContext cliContext, ValidationEngine validationEn if (cliContext.getSource() == null) { System.out.println("Must specify a source (-version)"); ok = false; - } else if (!new File(cliContext.getSource()).exists()) { + } else if (!ManagedFileAccess.file(cliContext.getSource()).exists()) { System.out.println("Factory source '"+cliContext.getSource()+"' not found"); ok = false; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java index c79439399e..efb8067f41 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java @@ -6,6 +6,7 @@ import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.utilities.TimeTracker; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.validation.ValidationEngine; import org.hl7.fhir.validation.cli.model.CliContext; import org.hl7.fhir.validation.cli.services.ValidationService; @@ -47,7 +48,7 @@ public void executeTask(ValidationService validationService, ValidationEngine va String pid = cliContext.getPackageName(); boolean json = cliContext.getFormat() != FhirFormat.XML; String output = cliContext.getOutput(); - File f = new File(output); + File f = ManagedFileAccess.file(output); ExpansionPackageGeneratorOutputType t = ExpansionPackageGeneratorOutputType.FOLDER; if (f.exists() && f.isDirectory()) { t = ExpansionPackageGeneratorOutputType.FOLDER; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java index 3a9ce88910..d6aba79d21 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java @@ -49,7 +49,11 @@ public void executeTask(CliContext cliContext, String[] args, TimeTracker tt, Ti if (output == null ) { output = Utilities.path("[tmp]"); } - boolean ok = new TxTester(new TxTester.InternalTxLoader(version), tx, false, loadExternals(externals)).setOutput(output).execute(cliContext.getModeParams(), filter); + TxTester txTester = new TxTester(new TxTester.InternalTxLoader(version), tx, false, loadExternals(externals)); + for (String input : cliContext.getInputs()) { + txTester.addLoader(new TxTester.InternalTxLoader(input, true)); + } + boolean ok = txTester.setOutput(output).execute(cliContext.getModeParams(), filter); SystemExitManager.setError(ok ? 0 : 1); SystemExitManager.finish(); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java index 05eb8304fd..61d69fb0fe 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java @@ -405,7 +405,7 @@ else if (args[i].equals(HTML_OUTPUT)) { cliContext.setOutputStyle(args[++i]); } else if (args[i].equals(ADVSIOR_FILE)) { cliContext.setAdvisorFile(args[++i]); - File f = new File(cliContext.getAdvisorFile()); + File f = ManagedFileAccess.file(cliContext.getAdvisorFile()); if (!f.exists()) { throw new Error("Cannot find advisor file "+cliContext.getAdvisorFile()); } else if (!Utilities.existsInList(Utilities.getFileExtension(f.getName()), "json", "txt")) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java index cb8a0040d8..2947ba3f7a 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java @@ -12,6 +12,7 @@ import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.json.model.JsonObject; import org.hl7.fhir.utilities.validation.ValidationOptions; @@ -174,7 +175,7 @@ public static String getDiffForValidation(String id, IWorkerContext context, Str parameters.addParameter(validationResult.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED ? "x-caused-by-unknown-system" : "x-unknown-system", new CanonicalType(s)); } } - if (validationResult.getIssues().size() > 0) { + if (validationResult.getIssues().size() > 0) { operationOutcome = new OperationOutcome(); operationOutcome.getIssue().addAll(validationResult.getIssues()); parameters.addParameter().setName("issues").setResource(operationOutcome); @@ -205,12 +206,12 @@ public static void writeDiffToFileSystem(String testName, String expected, Strin } String fullExpected = rootDirectory + "/expected/"; String fullActual = rootDirectory + "/actual/"; - File expectedDirectory = new File(fullExpected); + File expectedDirectory = ManagedFileAccess.file(fullExpected); if (!expectedDirectory.exists()) { expectedDirectory.mkdirs(); } - File actualDirectory = new File(fullActual); + File actualDirectory = ManagedFileAccess.file(fullActual); if (!actualDirectory.exists()) { actualDirectory.mkdirs(); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java index 42dbcc0d3a..b6311d5ecf 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java @@ -3,13 +3,17 @@ import lombok.Getter; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.utilities.json.JsonException; import org.hl7.fhir.utilities.json.model.JsonObject; import org.hl7.fhir.utilities.json.parser.JsonParser; import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.NpmPackage; +import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.*; public class TxTestData { @@ -24,17 +28,74 @@ public class TxTestData { private final List testData; private final NpmPackage npm; + private final File folder; + private final String code; + private final String version; + private final String testFileName; - private TxTestData(List testData, JsonObject manifest, JsonObject externals, NpmPackage npm) throws IOException { + private TxTestData(List testData, JsonObject manifest, JsonObject externals, NpmPackage npm, String code, String version) throws IOException { this.testData = testData; this.manifest = manifest; this.externals = externals; this.npm = npm; + this.folder = null; + this.code = code; + this.version = version; + this.testFileName = "test-cases.json"; + } + + private TxTestData(List testData, JsonObject manifest, JsonObject externals, File folder, String filename, String code, String version) throws IOException { + this.testData = testData; + this.manifest = manifest; + this.externals = externals; + this.npm = null; + this.folder = folder; + this.code = code; + this.version = version; + this.testFileName = filename; } - public static TxTestData loadTestDataFromPackage(String version) throws IOException { + public static TxTestData loadTestDataFromFolder(File folder, String name) throws IOException { + + String contents = TextFile.streamToString(loadFile(folder, name)); + String externalSource = ManagedFileAccess.file(folder.getAbsolutePath(), "messages-tx.fhir.org.json").exists() ? + TextFile.streamToString(loadFile(folder, "messages-tx.fhir.org.json")) : null; + JsonObject externals = externalSource == null ? new JsonObject() : org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(externalSource); + + Map examples = new HashMap(); + JsonObject manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents); + + for (JsonObject suite : manifest.getJsonObjects("suites")) { + if (!"tx.fhir.org".equals(suite.asString("mode"))) { + String sn = suite.asString("name"); + for (JsonObject test : suite.getJsonObjects("tests")) { + String tn = test.asString("name"); + examples.put(sn + "." + tn, new TxTestSetup(suite, test)); + } + } + } + + List names = new ArrayList(examples.size()); + names.addAll(examples.keySet()); + Collections.sort(names); + + List testData = new ArrayList(examples.size()); + for (String id : names) { + testData.add(new Object[]{id, examples.get(id)}); + } + + return new TxTestData(testData, manifest, externals, folder, name, manifest.asString("code"), manifest.asString("version")); + } + + private static InputStream loadFile(File folder, String filename) throws IOException { + File f = ManagedFileAccess.file(Utilities.path(folder.getAbsolutePath(), filename)); + + return ManagedFileAccess.inStream(f); + } + + public static TxTestData loadTestDataFromPackage(String source) throws IOException { FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build(); - NpmPackage npm = pcm.loadPackage("hl7.fhir.uv.tx-ecosystem", version); + NpmPackage npm = pcm.loadPackage(source); String contents = TextFile.streamToString(npm.load("tests", "test-cases.json")); String externalSource = TextFile.streamToString(npm.load("tests", "messages-tx.fhir.org.json")); @@ -61,23 +122,39 @@ public static TxTestData loadTestDataFromPackage(String version) throws IOExcept testData.add(new Object[]{id, examples.get(id)}); } - return new TxTestData(testData, manifest, externals, npm); + return new TxTestData(testData, manifest, externals, npm, manifest.asString("code"), manifest.asString("version")); } public String load(String fn) throws IOException { - return TextFile.streamToString(npm.load("tests", fn)); + if (folder != null) { + return TextFile.streamToString(loadFile(folder, fn)); + } else { + return TextFile.streamToString(npm.load("tests", fn)); + } } public byte[] loadBytes(String fn) throws IOException { - return TextFile.streamToBytes(npm.load("tests", fn)); + if (folder != null) { + return TextFile.streamToBytes(loadFile(folder, fn)); + } else { + return TextFile.streamToBytes(npm.load("tests", fn)); + } } public boolean hasFile(String filename) throws IOException { - return npm.hasFile("tests", filename); + if (folder != null) { + return ManagedFileAccess.file(Utilities.path(folder.getAbsolutePath(), filename)).exists(); + } else { + return npm.hasFile("tests", filename); + } } public String loadVersion() throws JsonException, IOException { - return readHistory(loadBytes("history.json")); + if (version == null) { + return readHistory(loadBytes("history.json")); + } else { + return version; + } } private String readHistory(byte[] content) throws JsonException, IOException { @@ -86,7 +163,19 @@ private String readHistory(byte[] content) throws JsonException, IOException { } public String describe() { - return npm.name()+"#"+npm.version(); + if (folder != null) { + return folder.getAbsolutePath(); + } else { + return npm.name()+"#"+npm.version(); + } + } + + public String code() { + return code; + } + + public String testFileName() { + return testFileName; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java index 4286573151..5cab0c76a6 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java @@ -38,6 +38,7 @@ 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.terminologies.client.ITerminologyClient.ITerminologyConversionLogger; import org.hl7.fhir.r5.test.utils.CompareUtilities; import org.hl7.fhir.r5.utils.client.EFhirClientException; import org.hl7.fhir.r5.utils.client.network.ClientHeaders; @@ -73,12 +74,42 @@ public interface ITxTesterLoader { public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException; public byte[] loadContent(String filename) throws FileNotFoundException, IOException; public boolean hasContent(String filename) throws IOException; + public String code(); + public String version() throws JsonException, IOException; + public String testFileName(); + } + + private class TxTesterConversionLogger implements ITerminologyConversionLogger { + + public String suiteName; + public String testName; + + @Override + public void log(String name, String resourceType, String version, byte[] cnt) { + if (!"expandValueset.response".equals(name)) { + return; + } + + String base; + try { + base = Utilities.path(outputDir, "conversions"); + if (ManagedFileAccess.file(base).exists()) { + String dir = Utilities.path(base, version, suiteName); + Utilities.createDirectory(dir); + String filename = Utilities.path(dir, testName+"."+resourceType+".json"); + TextFile.bytesToFile(cnt, filename); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } private String server; - private ITxTesterLoader loader; + private List loaders = new ArrayList<>(); private String error; - private String output; + private String outputDir; private ITerminologyClient terminologyClient; private boolean tight; private JsonObject externals; @@ -86,33 +117,44 @@ public interface ITxTesterLoader { private List fails = new ArrayList<>(); private CapabilityStatement cstmt; private TerminologyCapabilities tc; + private TxTesterConversionLogger conversionLogger; public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) { super(); this.server = server; - this.loader = loader; + this.loaders.add(loader); this.tight = tight; this.externals = externals; + conversionLogger = new TxTesterConversionLogger(); } public static void main(String[] args) throws Exception { new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2]), args.length == 5 ? JsonParser.parseObjectFromFile(args[4]) : null).execute(new ArrayList<>(), args[3]); } + public void addLoader(ITxTesterLoader loader) { + this.loaders.add(loader); + } + public boolean execute(List modes, String filter) throws IOException, URISyntaxException { - if (output == null) { - output = Utilities.path("[tmp]", serverId()); + if (outputDir == null) { + outputDir = Utilities.path("[tmp]", serverId()); } System.out.println("Run terminology service Tests"); - System.out.println(" Source for tests: "+loader.describe()); - System.out.println(" Output Directory: "+output); - if (!new File(output).exists()) { - Utilities.createDirectory(output); + System.out.println(" Source for tests: "+loaders.get(0).describe()); + for (ITxTesterLoader loader : loaders) { + if (loader != loaders.get(0)) { + System.out.println(" Additional Tests: "+loader.describe()); + } + } + System.out.println(" Output Directory: "+outputDir); + if (!ManagedFileAccess.file(outputDir).exists()) { + Utilities.createDirectory(outputDir); } - if (!new File(output).exists()) { - throw new IOException("Unable to create output directory "+output); + if (!ManagedFileAccess.file(outputDir).exists()) { + throw new IOException("Unable to create output directory "+outputDir); } System.out.println(" Term Service Url: "+server); System.out.println(" External Strings: "+(externals != null)); @@ -121,32 +163,37 @@ public boolean execute(List modes, String filter) throws IOException, UR if (filter != null) { System.out.println(" Filter Parameter: "+filter); } - + IntHolder counter = new IntHolder(); + IntHolder errCount = new IntHolder(); JsonObject json = new JsonObject(); + List versions = new ArrayList(); json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone()); try { - JsonObject tests = loadTests(); terminologyClient = 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, modes, filter, json.forceArray("suites"), counter) && ok; + for (ITxTesterLoader loader : loaders) { + JsonObject tests = loadTests(loader); + versions.add(new StringPair(loader.code(), loader.version())); + for (JsonObject suite : tests.getJsonObjects("suites")) { + if ((!suite.has("mode") || modes.contains(suite.asString("mode")))) { + if (suite.asBoolean("disabled")) { + // ok = true; + } else { + ok = runSuite(loader, suite, modes, filter, json.forceArray("suites"), counter, errCount) && ok; + } } } } - TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(output, "test-results.json")); + TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(outputDir, "test-results.json")); if (filter == null) { String m = modes.isEmpty() ? "[none]" : CommaSeparatedStringBuilder.join(";", modes); if (ok) { - System.out.println(software+" passed all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" passed all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+vString(versions)+", runner v"+VersionUtil.getBaseVersion()+")"); return true; } else { - System.out.println(software+" did not pass all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" failed "+errCount.total()+" of "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+vString(versions)+", runner v"+VersionUtil.getBaseVersion()+")"); System.out.println("Failed Tests: "+ CommaSeparatedStringBuilder.join(",", fails )); return false; } @@ -162,6 +209,24 @@ public boolean execute(List modes, String filter) throws IOException, UR } + private String vString(List versions) { + StringBuilder b = new StringBuilder(); + b.append(versions.get(0).getValue()); + if (versions.size() > 1) { + b.append("["); + for (int i = 1; i < versions.size(); i++) { + if (i > 1) { + b.append(","); + } + b.append(versions.get(i).getName()); + b.append(":"); + b.append(versions.get(i).getValue()); + } + b.append("]"); + } + return b.toString(); + } + private String timezone() { TimeZone tz = TimeZone.getDefault(); Calendar cal = GregorianCalendar.getInstance(tz); @@ -174,6 +239,8 @@ private String timezone() { } private boolean checkClient() { + conversionLogger.suiteName = "connect"; + conversionLogger.testName = "checkClient"; cstmt = terminologyClient.getCapabilitiesStatement(); if (cstmt.hasSoftware()) { software = cstmt.getSoftware().getName()+" v"+cstmt.getSoftware().getVersion(); @@ -182,75 +249,76 @@ private boolean checkClient() { return true; } - private JsonObject loadTests() throws JsonException, IOException { + private JsonObject loadTests(ITxTesterLoader loader) throws JsonException, IOException { System.out.println("Load Tests from "+loader.describe()); - return JsonParser.parseObject(loader.loadContent("test-cases.json")); + return JsonParser.parseObject(loader.loadContent(loader.testFileName())); } - public String loadVersion() throws JsonException, IOException { - if (loader.hasContent("history.json")) { - return readHistory(loader.loadContent("history.json")); - } else { - throw new Error("history.md is no longer supported"); - } - } - - private String readHistory(byte[] content) throws JsonException, IOException { - JsonObject json = JsonParser.parseObject(content); - return json.getJsonObjects("versions").get(0).asString("version"); - } private ITerminologyClient connectToServer(List modes) throws URISyntaxException, IOException { System.out.println("Connect to "+server); software = server; + + if (outputDir == null) { + outputDir = Utilities.path("[tmp]", serverId()); + } + + // todo: we don't necessarily want R4: + Utilities.createDirectory(Utilities.path(outputDir, "conversions", "r4")); + Utilities.createDirectory(Utilities.path(outputDir, "conversions", "r5")); ITerminologyClient client = new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null); + client.setConversionLogger(conversionLogger); return client; } - public String executeTest(JsonObject suite, JsonObject test, List modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { + public String executeTest(ITxTesterLoader loader, JsonObject suite, JsonObject test, List modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { error = null; if (terminologyClient == null) { terminologyClient = connectToServer(modes); checkClient(); } - List setup = loadSetupResources(suite); + List setup = loadSetupResources(loader, suite); - if (runTest(suite, test, setup, modes, "*", null, new IntHolder())) { + if (runTest(loader, suite, test, setup, modes, "*", null, new IntHolder())) { return null; } else { return error; } } - private boolean runSuite(JsonObject suite, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, FileNotFoundException, IOException { + private boolean runSuite(ITxTesterLoader loader, JsonObject suite, List modes, String filter, JsonArray output, IntHolder counter, IntHolder errCount) throws FHIRFormatError, FileNotFoundException, IOException { System.out.println("Group "+suite.asString("name")); JsonObject outputS = new JsonObject(); if (output != null) { output.add(outputS); } outputS.add("name", suite.asString("name")); - List setup = loadSetupResources(suite); + List setup = loadSetupResources(loader, suite); boolean ok = true; for (JsonObject test : suite.getJsonObjects("tests")) { if ((!test.has("mode") || modes.contains(test.asString("mode")))) { if (test.asBoolean("disabled")) { ok = true; } else { - ok = runTest(suite, test, setup, modes, filter, outputS.forceArray("tests"), counter) && ok; + boolean tok = runTest(loader, suite, test, setup, modes, filter, outputS.forceArray("tests"), counter); + if (!tok) { + errCount.count(); + } + ok = tok && ok; } } } return ok; } - private boolean runTest(JsonObject suite, JsonObject test, List setup, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private boolean runTest(ITxTesterLoader loader, JsonObject suite, JsonObject test, List setup, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { JsonObject outputT = new JsonObject(); if (output != null) { output.add(outputT); } long start = System.currentTimeMillis(); - Parameters profile = loadProfile(test); + Parameters profile = loadProfile(loader, test); outputT.add("name", test.asString("name")); if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) { System.out.print(" Test "+test.asString("name")+": "); @@ -264,13 +332,14 @@ private boolean runTest(JsonObject suite, JsonObject test, List setup, terminologyClient.setClientHeaders(new ClientHeaders(List.of(header))); } } - + conversionLogger.suiteName = suite.asString("name"); + conversionLogger.testName = test.asString("name"); 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)); - String fp = this.output == null ? Utilities.path("[tmp]", serverId(), fn) : Utilities.path(this.output, fn); + String fp = this.outputDir == null ? Utilities.path("[tmp]", serverId(), fn) : Utilities.path(this.outputDir, fn); File fo = ManagedFileAccess.file(fp); if (fo.exists()) { fo.delete(); @@ -373,7 +442,7 @@ private String chooseParam(JsonObject test, String name, List modes) { return test.asString(name); } - private Parameters loadProfile(JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private Parameters loadProfile(ITxTesterLoader loader, JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { if (test.has("profile")) { return (Parameters) loader.loadResource(test.asString("profile")); } else { @@ -560,7 +629,7 @@ private Map vars() { } - private List loadSetupResources(JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException { + private List loadSetupResources(ITxTesterLoader loader, JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException { List res = new ArrayList<>(); for (String s : suite.getStrings("setup")) { res.add(loader.loadResource(s)); @@ -569,27 +638,44 @@ private List loadSetupResources(JsonObject suite) throws FHIRFormatErr } public String getOutput() { - return output; + return outputDir; } public TxTester setOutput(String output) { - this.output = output; + this.outputDir = output; return this; } public static class InternalTxLoader implements ITxTesterLoader { - TxTestData txtests; + private TxTestData txtests; + private boolean additional; public InternalTxLoader(String version) throws IOException { - load(version); + File f = ManagedFileAccess.file(version); + if (f.exists() && f.isDirectory()) { + txtests = TxTestData.loadTestDataFromFolder(f, "test-cases.json"); + } else { + load(version); + } + } + + public InternalTxLoader(String source, boolean additional) throws IOException { + this.additional = additional; + File f = ManagedFileAccess.file(source); + if (f.exists() && f.isDirectory()) { + txtests = TxTestData.loadTestDataFromFolder(f, "test-cases.json"); + } else if (f.exists()) { + txtests = TxTestData.loadTestDataFromFolder(ManagedFileAccess.file(Utilities.getDirectoryForFile(source)), f.getName()); + } else { + load(source); + } } private void load(String version) throws IOException { - txtests = TxTestData.loadTestDataFromPackage(version); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#"+version); } - @Override public String describe() { return txtests.describe(); @@ -617,6 +703,22 @@ public byte[] loadContent(String filename) throws FileNotFoundException, IOExcep public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return txtests.code(); + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } + } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java index 02b5b6a159..e7fa225f92 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java @@ -21,6 +21,7 @@ import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.Resource; +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.validation.special.TxTestData; @@ -52,7 +53,7 @@ public JsonObjectPair(JsonObject suite, JsonObject test) { @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-tx.fhir.org.json")); @@ -101,7 +102,7 @@ public void test() throws Exception { if (setup.suite.asBoolean("disabled") || setup.test.asBoolean("disabled")) { return; } - String err = tester.executeTest(setup.suite, setup.test, modes); + String err = tester.executeTest(this, setup.suite, setup.test, modes); Assertions.assertTrue(err == null, err); } else { Assertions.assertTrue(true); @@ -155,4 +156,19 @@ public byte[] loadContent(String filename) throws FileNotFoundException, IOExcep public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return "external"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java index 284590b1bb..c38edfe117 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java @@ -62,7 +62,7 @@ private static boolean localTxRunning() throws IOException { @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-tx.fhir.org.json")); @@ -95,7 +95,8 @@ public static Iterable data() throws IOException { private String version = "5.0.0"; private static TxTester tester; private List modes = new ArrayList<>(); - private boolean error = false; + private static int error = 0; + private static int count = 0; private static TxTestData txtests; public LocalTerminologyServiceTests(String name, JsonObjectPair setup) { @@ -115,17 +116,23 @@ public void test() throws Exception { return; } 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()+")"); + count++; + if (error == 0) { + System.out.println("tx.fhir.org passed all "+count+" HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + } else { + System.out.println("tx.fhir.org failed "+error+" of "+count+" HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); } - Assertions.assertTrue(!error); + Assertions.assertTrue(error == 0); } else { + count++; 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; + String err = tester.executeTest(this, setup.suite, setup.test, modes); + if (err != null) { + error++; + } Assertions.assertTrue(err == null, err); } else { Assertions.assertTrue(true); @@ -175,10 +182,6 @@ else if (org.hl7.fhir.r4.model.Constants.VERSION.equals(version) || "4.0".equals throw new FHIRException("unknown version " + version); } } -// org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(res); -// String p = Utilities.path(FhirSettings.getFhirTestCasesPath(), "tx", "r4", filename); -// Utilities.createDirectory(Utilities.getDirectoryForFile(p)); -// new org.hl7.fhir.r4.formats.JsonParser().compose(ManagedFileAccess.outStream(p), r4); return res; } @@ -196,4 +199,21 @@ public byte[] loadContent(String filename) throws FileNotFoundException, IOExcep public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return "local"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java index e5b9017cf8..1bba73505f 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java @@ -20,6 +20,7 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.utilities.Utilities; 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; @@ -54,12 +55,10 @@ private static boolean localTxRunning() throws IOException { return ManagedFileAccess.file("/Users/grahamegrieve/work/server/server").exists(); } - - @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-ontoserver.csiro.au.json")); @@ -117,7 +116,7 @@ public void test() throws Exception { if (tester == null) { tester = new TxTester(this, SERVER, false, externals); } - String err = tester.executeTest(setup.suite, setup.test, modes); + String err = tester.executeTest(this, setup.suite, setup.test, modes); if (err != null) { System.out.println(err); } @@ -161,10 +160,6 @@ else if (org.hl7.fhir.r4.model.Constants.VERSION.equals(version) || "4.0".equals throw new FHIRException("unknown version " + version); } } -// org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(res); -// String p = Utilities.path(FhirSettings.getFhirTestCasesPath(), "tx", "r4", filename); -// Utilities.createDirectory(Utilities.getDirectoryForFile(p)); -// new org.hl7.fhir.r4.formats.JsonParser().compose(ManagedFileAccess.outStream(p), r4); return res; } @@ -182,4 +177,21 @@ public byte[] loadContent(String filename) throws FileNotFoundException, IOExcep public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + + + @Override + public String code() { + return "onto"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java index 182dad9af6..bcddc4f698 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java @@ -59,7 +59,7 @@ public class TerminologyServiceTests { @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - testData = TxTestData.loadTestDataFromPackage("dev"); + testData = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); return testData.getTestData(); }