From a04b90005434f9c255da7ecda8e5db8002f58108 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 8 Feb 2019 16:56:53 +1100 Subject: [PATCH] fix tests --- .../fhir/r4/test/SnapShotGenerationTests.java | 185 +++++++++--------- .../fhir/r4/validation/InstanceValidator.java | 52 +++-- .../fhir/r4/validation/ValidationEngine.java | 22 ++- 3 files changed, 151 insertions(+), 108 deletions(-) diff --git a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/SnapShotGenerationTests.java b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/SnapShotGenerationTests.java index c22ed69e7..b8ab09d00 100644 --- a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/SnapShotGenerationTests.java @@ -146,13 +146,13 @@ public class SnapShotGenerationTests { if (!test.getActionFirstRep().hasOperation()) throw new Error("Unsupported: first action must be an operation"); for (int i = 0; i < test.getAction().size(); i++) { -// if (!test.getAction().get(i).hasAssert()) -// throw new Error("Unsupported: following actions must be an asserts"); + // if (!test.getAction().get(i).hasAssert()) + // throw new Error("Unsupported: following actions must be an asserts"); TestActionComponent action = test.getAction().get(i); if (action.hasOperation()) { SetupActionOperationComponent op = test.getActionFirstRep().getOperation(); if (!CodingUtilities.matches(op.getType(), "http://hl7.org/fhir/testscript-operation-codes", "snapshot") - && !CodingUtilities.matches(op.getType(), "http://hl7.org/fhir/testscript-operation-codes", "sortDifferential")) + && !CodingUtilities.matches(op.getType(), "http://hl7.org/fhir/testscript-operation-codes", "sortDifferential")) throw new Error("Unsupported action operation type "+CodingUtilities.present(op.getType())); if (!"StructureDefinition".equals(op.getResource())) throw new Error("Unsupported action operation resource "+op.getResource()); @@ -192,7 +192,7 @@ public class SnapShotGenerationTests { public Resource fetchFixture(String id) { if (fixtures.containsKey(id)) return fixtures.get(id); - + for (TestScriptFixtureComponent ds : tests.getFixture()) { if (id.equals(ds.getId())) throw new Error("not done yet"); @@ -304,108 +304,107 @@ public class SnapShotGenerationTests { @Test public void test() throws FHIRException { try { - for (Resource cr : context.tests.getContained()) { - if (cr instanceof StructureDefinition) { - StructureDefinition sd = (StructureDefinition) cr; - if (sd.getType().equals("Extension")) { - if (TestingUtilities.context().fetchResource(StructureDefinition.class, sd.getUrl()) == null) { - sd.setUserData("path", "test-"+sd.getId()+".html"); - StructureDefinition extd = TestingUtilities.context().fetchResource(StructureDefinition.class, sd.getBaseDefinition()); - new ProfileUtilities(TestingUtilities.context(), null, null).generateSnapshot(extd, sd, sd.getUrl(), sd.getName()); - TestingUtilities.context().cacheResource(sd); - debugSaveResource(sd); + for (Resource cr : context.tests.getContained()) { + if (cr instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) cr; + if (sd.getType().equals("Extension")) { + if (TestingUtilities.context().fetchResource(StructureDefinition.class, sd.getUrl()) == null) { + sd.setUserData("path", "test-"+sd.getId()+".html"); + StructureDefinition extd = TestingUtilities.context().fetchResource(StructureDefinition.class, sd.getBaseDefinition()); + new ProfileUtilities(TestingUtilities.context(), null, null).generateSnapshot(extd, sd, sd.getUrl(), sd.getName()); + TestingUtilities.context().cacheResource(sd); + debugSaveResource(sd); + } } } } - } - if (fp == null) - fp = new FHIRPathEngine(TestingUtilities.context()); - fp.setHostServices(context); + if (fp == null) + fp = new FHIRPathEngine(TestingUtilities.context()); + fp.setHostServices(context); - resolveFixtures(); - - TestScript.AssertionResponseTypes lastOpOutcome = null; - for (int i = 0; i < test.getAction().size(); i++) { - TestActionComponent action = test.getAction().get(i); - if (action.hasOperation()) { - lastOpOutcome = AssertionResponseTypes.OKAY; - try { - SetupActionOperationComponent op = action.getOperation(); - Coding opType = op.getType(); - if (opType.getSystem().equals("http://hl7.org/fhir/testscript-operation-codes") && opType.getCode().equals("snapshot")) { - StructureDefinition source = (StructureDefinition) context.fetchFixture(op.getSourceId()); - StructureDefinition base = getSD(source.getBaseDefinition()); - StructureDefinition output = source.copy(); - ProfileUtilities pu = new ProfileUtilities(TestingUtilities.context(), null, new TestPKP()); - pu.setIds(source, false); - if ("sort=true".equals(op.getParams())) { - List errors = new ArrayList(); - pu.sortDifferential(base, output, source.getName(), errors); - if (errors.size() > 0) - throw new FHIRException("Sort failed: "+errors.toString()); + resolveFixtures(); + + TestScript.AssertionResponseTypes lastOpOutcome = null; + for (int i = 0; i < test.getAction().size(); i++) { + TestActionComponent action = test.getAction().get(i); + if (action.hasOperation()) { + lastOpOutcome = AssertionResponseTypes.OKAY; + try { + SetupActionOperationComponent op = action.getOperation(); + Coding opType = op.getType(); + if (opType.getSystem().equals("http://hl7.org/fhir/testscript-operation-codes") && opType.getCode().equals("snapshot")) { + StructureDefinition source = (StructureDefinition) context.fetchFixture(op.getSourceId()); + StructureDefinition base = getSD(source.getBaseDefinition()); + StructureDefinition output = source.copy(); + ProfileUtilities pu = new ProfileUtilities(TestingUtilities.context(), null, new TestPKP()); + pu.setIds(source, false); + if ("sort=true".equals(op.getParams())) { + List errors = new ArrayList(); + int lastCount = output.getDifferential().getElement().size(); + pu.sortDifferential(base, output, source.getName(), errors); + if (errors.size() > 0) + throw new FHIRException("Sort failed: "+errors.toString()); + if (lastCount != output.getDifferential().getElement().size()) + throw new FHIRException("Sort failed: counts differ; at least one of the paths in the differential is illegal"); + + } + pu.generateSnapshot(base, output, source.getUrl(), source.getName()); + debugSaveResource(output); + context.fixtures.put(op.getResponseId(), output); + context.snapshots.put(output.getUrl(), output); + + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); + if (output.getDifferential().hasElement()) + new NarrativeGenerator("", "http://hl7.org/fhir", TestingUtilities.context()).setPkp(new TestPKP()).generate(output, null); + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+"-d.xml")), output); + } else if (opType.getSystem().equals("http://hl7.org/fhir/testscript-operation-codes") && opType.getCode().equals("sortDifferential")) { + StructureDefinition source = (StructureDefinition) context.fetchFixture(op.getSourceId()); + StructureDefinition base = getSD(source.getBaseDefinition()); + StructureDefinition output = source.copy(); + ProfileUtilities pu = new ProfileUtilities(TestingUtilities.context(), null, null); + pu.setIds(source, false); + List errors = new ArrayList(); + pu.sortDifferential(base, output, output.getUrl(), errors); + if (!errors.isEmpty()) + throw new FHIRException(errors.get(0)); + context.fixtures.put(op.getResponseId(), output); + context.snapshots.put(output.getUrl(), output); + + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); + + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); + } else if (action.hasAssert()) { + SetupActionAssertComponent a = action.getAssert(); + if (a.hasResponse() && a.getResponse().equals(TestScript.AssertionResponseTypes.BAD)) + Assert.fail(action.getAssert().getLabel()+": "+action.getAssert().getDescription()); + else { + boolean ok = fp.evaluateToBoolean(new StructureDefinition(), new StructureDefinition(), a.getExpression()); + Assert.assertTrue(a.getLabel()+": "+a.getDescription(), ok); + } + } else { + throw new Error("Unsupported operation: " + opType.getSystem() + " : " + opType.getCode()); + } + lastOpOutcome = AssertionResponseTypes.OKAY; + } catch (Exception e) { + for (int j = i+1;i < test.getAction().size(); i++) { + TestActionComponent followAction = test.getAction().get(j); + if (followAction.hasAssert() && followAction.getAssert().hasResponse() && followAction.getAssert().getResponse().equals(TestScript.AssertionResponseTypes.BAD)) { + lastOpOutcome = AssertionResponseTypes.BAD; + break; + } } - pu.generateSnapshot(base, output, source.getUrl(), source.getName()); - debugSaveResource(output); - context.fixtures.put(op.getResponseId(), output); - context.snapshots.put(output.getUrl(), output); - - new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); - if (output.getDifferential().hasElement()) - new NarrativeGenerator("", "http://hl7.org/fhir", TestingUtilities.context()).setPkp(new TestPKP()).generate(output, null); - new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+"-d.xml")), output); - } else if (opType.getSystem().equals("http://hl7.org/fhir/testscript-operation-codes") && opType.getCode().equals("sortDifferential")) { - StructureDefinition source = (StructureDefinition) context.fetchFixture(op.getSourceId()); - StructureDefinition base = getSD(source.getBaseDefinition()); - StructureDefinition output = source.copy(); - ProfileUtilities pu = new ProfileUtilities(TestingUtilities.context(), null, null); - pu.setIds(source, false); - List errors = new ArrayList(); - pu.sortDifferential(base, output, output.getUrl(), errors); - if (!errors.isEmpty()) - throw new FHIRException(errors.get(0)); - context.fixtures.put(op.getResponseId(), output); - context.snapshots.put(output.getUrl(), output); - - new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); - - new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(System.getProperty("java.io.tmpdir"), op.getResponseId()+".xml")), output); - - } else { - throw new Error("Unsupported operation: " + opType.getSystem() + " : " + opType.getCode()); } } else if (action.hasAssert()) { SetupActionAssertComponent a = action.getAssert(); - if (a.hasResponse() && a.getResponse().equals(TestScript.AssertionResponseTypes.BAD)) - Assert.fail(action.getAssert().getLabel()+": "+action.getAssert().getDescription()); - else { + if (a.getResponse() != null) { + Assert.assertTrue(a.getLabel()+" (response): "+a.getDescription(), a.getResponse() == lastOpOutcome); + } + if (a.hasExpression()) { boolean ok = fp.evaluateToBoolean(new StructureDefinition(), new StructureDefinition(), a.getExpression()); Assert.assertTrue(a.getLabel()+": "+a.getDescription(), ok); } } - } catch (Exception e) { - boolean ok = false; - for (int j = i+1;i < test.getAction().size(); i++) { - TestActionComponent followAction = test.getAction().get(j); - if (followAction.hasAssert() && followAction.getAssert().hasResponse() && followAction.getAssert().getResponse().equals(TestScript.AssertionResponseTypes.BAD)) { - ok = true; - break; - } - } - } catch (Exception e) { - lastOpOutcome = AssertionResponseTypes.BAD; - } - - } else if (action.hasAssert()) { - SetupActionAssertComponent a = action.getAssert(); - if (a.getResponse() != null) { - Assert.assertTrue(a.getLabel()+" (response): "+a.getDescription(), a.getResponse() == lastOpOutcome); - } - if (a.hasExpression()) { - boolean ok = fp.evaluateToBoolean(new StructureDefinition(), new StructureDefinition(), a.getExpression()); - Assert.assertTrue(a.getLabel()+": "+a.getDescription(), ok); - } } - } } catch (Exception e) { e.printStackTrace(); throw new FHIRException(e); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java index 15ece9bee..cb403e9ce 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java @@ -216,8 +216,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat @Override public Base resolveReference(Object appContext, String url) throws FHIRException { ValidatorHostContext c = (ValidatorHostContext) appContext; - if (c.container != null || externalHostServices == null) - throw new Error("Not done yet - resolve "+url+" locally"); + if (c.container != null) + throw new Error("Not done yet - resolve "+url+" locally (1)"); + else if (externalHostServices == null) + throw new Error("Not done yet - resolve "+url+" locally (2)"); else return externalHostServices.resolveReference(c.appContext, url); @@ -3291,12 +3293,22 @@ private String misplacedItemError(QuestionnaireItemComponent qItem) { String url = getCanonicalURLForEntry(entry); String id = getIdForEntry(entry); if (url != null) { - rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), !url.equals(fullUrl) || (url.matches(Constants.URI_REGEX) && url.endsWith("/"+id)), "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless the resource id ("+id+") also matches"); + if (!(!url.equals(fullUrl) || (url.matches(uriRegexForVersion()) && url.endsWith("/"+id)))) + rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), false, "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless the resource id ("+id+") also matches"); rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild("resource").fhirType(), id))), "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless on the canonical server itself"); } } } + public final static String URI_REGEX3 = "((http|https)://([A-Za-z0-9\\\\\\.\\:\\%\\$]*\\/)*)?(Account|ActivityDefinition|AllergyIntolerance|AdverseEvent|Appointment|AppointmentResponse|AuditEvent|Basic|Binary|BodySite|Bundle|CapabilityStatement|CarePlan|CareTeam|ChargeItem|Claim|ClaimResponse|ClinicalImpression|CodeSystem|Communication|CommunicationRequest|CompartmentDefinition|Composition|ConceptMap|Condition (aka Problem)|Consent|Contract|Coverage|DataElement|DetectedIssue|Device|DeviceComponent|DeviceMetric|DeviceRequest|DeviceUseStatement|DiagnosticReport|DocumentManifest|DocumentReference|EligibilityRequest|EligibilityResponse|Encounter|Endpoint|EnrollmentRequest|EnrollmentResponse|EpisodeOfCare|ExpansionProfile|ExplanationOfBenefit|FamilyMemberHistory|Flag|Goal|GraphDefinition|Group|GuidanceResponse|HealthcareService|ImagingManifest|ImagingStudy|Immunization|ImmunizationRecommendation|ImplementationGuide|Library|Linkage|List|Location|Measure|MeasureReport|Media|Medication|MedicationAdministration|MedicationDispense|MedicationRequest|MedicationStatement|MessageDefinition|MessageHeader|NamingSystem|NutritionOrder|Observation|OperationDefinition|OperationOutcome|Organization|Parameters|Patient|PaymentNotice|PaymentReconciliation|Person|PlanDefinition|Practitioner|PractitionerRole|Procedure|ProcedureRequest|ProcessRequest|ProcessResponse|Provenance|Questionnaire|QuestionnaireResponse|ReferralRequest|RelatedPerson|RequestGroup|ResearchStudy|ResearchSubject|RiskAssessment|Schedule|SearchParameter|Sequence|ServiceDefinition|Slot|Specimen|StructureDefinition|StructureMap|Subscription|Substance|SupplyDelivery|SupplyRequest|Task|TestScript|TestReport|ValueSet|VisionPrescription)\\/[A-Za-z0-9\\-\\.]{1,64}(\\/_history\\/[A-Za-z0-9\\-\\.]{1,64})?"; + + private String uriRegexForVersion() { + if ("3.0.1".equals(context.getVersion())) + return URI_REGEX3; + else + return Constants.URI_REGEX; + } + private String getCanonicalURLForEntry(Element entry) { Element e = entry.getNamedChild("resource"); if (e == null) @@ -3961,16 +3973,16 @@ private String misplacedItemError(QuestionnaireItemComponent qItem) { if (inv.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice") && ToolingExtensions.readBooleanExtension(inv, "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice")) { if (bpWarnings == BestPracticeWarningLevel.Hint) - hint(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+inv.getExpression()+"]"); + hint(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+n.toString()+"]"); else if (bpWarnings == BestPracticeWarningLevel.Warning) - warning(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+inv.getExpression()+"]"); + warning(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+n.toString()+"]"); else if (bpWarnings == BestPracticeWarningLevel.Error) - rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+inv.getExpression()+"]"); + rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+n.toString()+"]"); } if (inv.getSeverity() == ConstraintSeverity.ERROR) - rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+inv.getExpression()+"]"); + rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getHuman()+msg+" ["+n.toString()+"]"); else if (inv.getSeverity() == ConstraintSeverity.WARNING) - warning(errors, IssueType.INVARIANT, element.line(), element.line(), path, ok, inv.getHuman()+msg+" ["+inv.getExpression()+"]"); + warning(errors, IssueType.INVARIANT, element.line(), element.line(), path, ok, inv.getHuman()+msg+" ["+n.toString()+"]"); } } @@ -4346,6 +4358,7 @@ private String misplacedItemError(QuestionnaireItemComponent qItem) { private String fixExpr(String expr) { // this is a hack work around for past publication of wrong FHIRPath expressions + // R4 if ("(component.empty() and hasMember.empty()) implies (dataAbsentReason or value)".equals(expr)) return "(component.empty() and hasMember.empty()) implies (dataAbsentReason.exists() or value.exists())"; if ("isModifier implies isModifierReason.exists()".equals(expr)) @@ -4356,10 +4369,25 @@ private String misplacedItemError(QuestionnaireItemComponent qItem) { return "differential.element.all(id.exists()) and differential.element.id.trace('ids').isDistinct()"; if ("snapshot.element.all(id) and snapshot.element.id.trace('ids').isDistinct()".equals(expr)) return "snapshot.element.all(id.exists()) and snapshot.element.id.trace('ids').isDistinct()"; - if ("".equals(expr)) - return ""; - if ("".equals(expr)) - return ""; + + // R3 + if ("(code or value.empty()) and (system.empty() or system = 'urn:iso:std:iso:4217')".equals(expr)) + return "(code.exists() or value.empty()) and (system.empty() or system = 'urn:iso:std:iso:4217')"; + if ("value.empty() or code!=component.code".equals(expr)) + return "value.empty() or (code in component.code).not()"; + if ("(code or value.empty()) and (system.empty() or system = %ucum) and (value.empty() or value > 0)".equals(expr)) + return "(code.exists() or value.empty()) and (system.empty() or system = %ucum) and (value.empty() or value > 0)"; + if ("element.all(definition and min and max)".equals(expr)) + return "element.all(definition.exists() and min.exists() and max.exists())"; + if ("telecom or endpoint".equals(expr)) + return "telecom.exists() or endpoint.exists()"; + if ("(code or value.empty()) and (system.empty() or system = %ucum) and (value.empty() or value > 0)".equals(expr)) + return "(code.exists() or value.empty()) and (system.empty() or system = %ucum) and (value.empty() or value > 0)"; + if ("searchType implies type = 'string'".equals(expr)) + return "searchType.exists() implies type = 'string'"; + if ("abatement.empty() or (abatement as boolean).not() or clinicalStatus='resolved' or clinicalStatus='remission' or clinicalStatus='inactive'".equals(expr)) + return "abatement.empty() or (abatement is boolean).not() or (abatement as boolean).not() or (clinicalStatus = 'resolved') or (clinicalStatus = 'remission') or (clinicalStatus = 'inactive')"; + if ("".equals(expr)) return ""; return expr; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/ValidationEngine.java index c4c0cf989..c1e82ed2a 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/ValidationEngine.java @@ -770,9 +770,17 @@ public class ValidationEngine { results.setType(Bundle.BundleType.COLLECTION); for (String ref : refs) { Content cnt = loadContent(ref, "validate"); - OperationOutcome outcome = validate(ref, cnt.focus, cnt.cntType, profiles); - ToolingExtensions.addStringExtension(outcome, ToolingExtensions.EXT_OO_FILE, ref); - results.addEntry().setResource(outcome); + if (refs.size() > 1) + System.out.println("Validate "+ref); + try { + OperationOutcome outcome = validate(ref, cnt.focus, cnt.cntType, profiles); + ToolingExtensions.addStringExtension(outcome, ToolingExtensions.EXT_OO_FILE, ref); + if (refs.size() > 1) + produceValidationSummary(outcome); + results.addEntry().setResource(outcome); + } catch (Throwable e) { + System.out.println("Validation Infrastructure fail validating "+ref+": "+e.getMessage()); + } } if (asBundle) return results; @@ -780,6 +788,14 @@ public class ValidationEngine { return results.getEntryFirstRep().getResource(); } + private void produceValidationSummary(OperationOutcome oo) { + for (OperationOutcomeIssueComponent iss : oo.getIssue()) { + if (iss.getSeverity() == org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity.ERROR || iss.getSeverity() == org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity.FATAL) { + System.out.println(" "+iss.getSeverity().toCode()+": "+iss.getDetails().getText()); + } + } + } + public OperationOutcome validateString(String location, String source, FhirFormat format, List profiles) throws Exception { return validate(location, source.getBytes(), format, profiles); }