fix how CodeableConcept is validated, and add Tx interaction logging by validator
This commit is contained in:
parent
46e1e5edd4
commit
ef085a847e
|
@ -26,7 +26,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.dstu2.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.HTMLClientLogger;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
|
@ -81,7 +81,7 @@ public class TerminologyClientR2 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setLogger(HTMLClientLogger txLog) {
|
||||
public void setLogger(ToolingClientLogger txLog) {
|
||||
// ignored in this version - need to roll R4 internal changes back to R2 if desired
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.dstu3.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.HTMLClientLogger;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
|
@ -79,7 +79,7 @@ public class TerminologyClientR3 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setLogger(HTMLClientLogger txLog) {
|
||||
public void setLogger(ToolingClientLogger txLog) {
|
||||
// ignored in this version - need to roll R4 internal changes back to R2 if desired
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.HTMLClientLogger;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
|
@ -79,7 +79,7 @@ public class TerminologyClientR4 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setLogger(HTMLClientLogger txLog) {
|
||||
public void setLogger(ToolingClientLogger txLog) {
|
||||
// ignored in this version - need to roll R4 internal changes back to R2 if desired
|
||||
}
|
||||
|
||||
|
|
|
@ -79,12 +79,14 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla
|
|||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.OIDUtils;
|
||||
import org.hl7.fhir.utilities.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.utilities.TranslationServices;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions.ValueSetMode;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
||||
|
@ -148,7 +150,7 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
private boolean allowLoadingDuplicates;
|
||||
|
||||
protected TerminologyClient txClient;
|
||||
protected HTMLClientLogger txLog;
|
||||
protected ToolingClientLogger txLog;
|
||||
private TerminologyCapabilities txcaps;
|
||||
private boolean canRunWithoutTerminology;
|
||||
protected boolean noTerminologyServer;
|
||||
|
@ -593,8 +595,12 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
}
|
||||
|
||||
private void setTerminologyOptions(ValidationOptions options, Parameters pIn) {
|
||||
if (!Utilities.noString(options.getLanguage()))
|
||||
if (!Utilities.noString(options.getLanguage())) {
|
||||
pIn.addParameter("displayLanguage", options.getLanguage());
|
||||
}
|
||||
if (options.getValueSetMode() != ValueSetMode.ALL_CHECKS) {
|
||||
pIn.addParameter("valueSetMode", options.getValueSetMode().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -241,7 +241,11 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
try {
|
||||
tlog("Connect to "+client.getAddress());
|
||||
txClient = client;
|
||||
txLog = new HTMLClientLogger(log);
|
||||
if (log != null && log.endsWith(".txt")) {
|
||||
txLog = new TextClientLogger(log);
|
||||
} else {
|
||||
txLog = new HTMLClientLogger(log);
|
||||
}
|
||||
txClient.setLogger(txLog);
|
||||
return txClient.getCapabilitiesStatementQuick().getSoftware().getVersion();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package org.hl7.fhir.r5.context;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* org.hl7.fhir.r5
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2019 Health Level 7
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TextClientLogger implements ToolingClientLogger {
|
||||
|
||||
private PrintStream file;
|
||||
private int id = 0;
|
||||
private String lastId;
|
||||
|
||||
public TextClientLogger(String log) {
|
||||
if (log != null) {
|
||||
try {
|
||||
file = new PrintStream(new FileOutputStream(log));
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logRequest(String method, String url, List<String> headers, byte[] body) {
|
||||
if (file == null)
|
||||
return;
|
||||
id++;
|
||||
lastId = Integer.toString(id);
|
||||
file.println("\r\n--- "+lastId+" -----------------\r\nRequest: \r\n");
|
||||
file.println(method+" "+url+" HTTP/1.0");
|
||||
for (String s : headers)
|
||||
file.println(Utilities.escapeXml(s));
|
||||
if (body != null) {
|
||||
file.println("");
|
||||
try {
|
||||
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
if (file == null)
|
||||
return;
|
||||
file.println("\r\n\r\nResponse: \r\n");
|
||||
file.println(outcome);
|
||||
for (String s : headers)
|
||||
file.println(Utilities.escapeXml(s));
|
||||
if (body != null) {
|
||||
file.println("");
|
||||
try {
|
||||
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getLastId() {
|
||||
return lastId;
|
||||
}
|
||||
|
||||
public void clearLastId() {
|
||||
lastId = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,7 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
|
||||
public interface TerminologyClient {
|
||||
public String getAddress();
|
||||
|
@ -37,7 +38,7 @@ public interface TerminologyClient {
|
|||
public Parameters validateCS(Parameters pin) throws FHIRException;
|
||||
public Parameters validateVS(Parameters pin) throws FHIRException;
|
||||
public void setTimeout(int i) throws FHIRException;
|
||||
public void setLogger(HTMLClientLogger txLog) throws FHIRException;
|
||||
public void setLogger(ToolingClientLogger txLog) throws FHIRException;
|
||||
public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException;
|
||||
public Parameters lookupCode(Map<String, String> params) throws FHIRException;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hl7.fhir.r5.model.Parameters;
|
|||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.r5.utils.client.ToolingClientLogger;
|
||||
|
||||
public class TerminologyClientR5 implements TerminologyClient {
|
||||
|
||||
|
@ -71,7 +72,7 @@ public class TerminologyClientR5 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setLogger(HTMLClientLogger txLog) {
|
||||
public void setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
|||
import org.hl7.fhir.utilities.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions.ValueSetMode;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
||||
public class ValueSetCheckerSimple implements ValueSetChecker {
|
||||
|
@ -67,22 +68,24 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
|
|||
// first, we validate the codings themselves
|
||||
List<String> errors = new ArrayList<String>();
|
||||
List<String> warnings = new ArrayList<String>();
|
||||
for (Coding c : code.getCoding()) {
|
||||
if (!c.hasSystem())
|
||||
warnings.add("Coding has no system - cannot validate");
|
||||
CodeSystem cs = context.fetchCodeSystem(c.getSystem());
|
||||
ValidationResult res = null;
|
||||
if (cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) {
|
||||
res = context.validateCode(options.noClient(), c, null);
|
||||
} else {
|
||||
res = validateCode(c, cs);
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
for (Coding c : code.getCoding()) {
|
||||
if (!c.hasSystem())
|
||||
warnings.add("Coding has no system - cannot validate");
|
||||
CodeSystem cs = context.fetchCodeSystem(c.getSystem());
|
||||
ValidationResult res = null;
|
||||
if (cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) {
|
||||
res = context.validateCode(options.noClient(), c, null);
|
||||
} else {
|
||||
res = validateCode(c, cs);
|
||||
}
|
||||
if (!res.isOk())
|
||||
errors.add(res.getMessage());
|
||||
else if (res.getMessage() != null)
|
||||
warnings.add(res.getMessage());
|
||||
}
|
||||
if (!res.isOk())
|
||||
errors.add(res.getMessage());
|
||||
else if (res.getMessage() != null)
|
||||
warnings.add(res.getMessage());
|
||||
}
|
||||
if (valueset != null) {
|
||||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
boolean ok = false;
|
||||
for (Coding c : code.getCoding()) {
|
||||
ok = ok || codeInValueSet(c.getSystem(), c.getCode());
|
||||
|
@ -101,38 +104,45 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
|
|||
public ValidationResult validateCode(Coding code) throws FHIRException {
|
||||
String warningMessage = null;
|
||||
// first, we validate the concept itself
|
||||
|
||||
String system = code.hasSystem() ? code.getSystem() : getValueSetSystem();
|
||||
if (system == null && !code.hasDisplay()) { // dealing with just a plain code (enum)
|
||||
system = systemForCodeInValueSet(code.getCode());
|
||||
}
|
||||
if (!code.hasSystem())
|
||||
code.setSystem(system);
|
||||
boolean inExpansion = checkExpansion(code);
|
||||
CodeSystem cs = context.fetchCodeSystem(system);
|
||||
if (cs == null) {
|
||||
warningMessage = "Unable to resolve system "+system+" - system is not specified or implicit";
|
||||
if (!inExpansion)
|
||||
throw new FHIRException(warningMessage);
|
||||
}
|
||||
if (cs!=null && cs.getContent() != CodeSystemContentMode.COMPLETE) {
|
||||
warningMessage = "Unable to resolve system "+system+" - system is not complete";
|
||||
if (!inExpansion)
|
||||
throw new FHIRException(warningMessage);
|
||||
}
|
||||
|
||||
|
||||
ValidationResult res =null;
|
||||
if (cs!=null)
|
||||
res = validateCode(code, cs);
|
||||
|
||||
boolean inExpansion = false;
|
||||
String system = code.hasSystem() ? code.getSystem() : getValueSetSystem();
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
if (system == null && !code.hasDisplay()) { // dealing with just a plain code (enum)
|
||||
system = systemForCodeInValueSet(code.getCode());
|
||||
}
|
||||
if (!code.hasSystem())
|
||||
code.setSystem(system);
|
||||
inExpansion = checkExpansion(code);
|
||||
CodeSystem cs = context.fetchCodeSystem(system);
|
||||
if (cs == null) {
|
||||
warningMessage = "Unable to resolve system "+system+" - system is not specified or implicit";
|
||||
if (!inExpansion)
|
||||
throw new FHIRException(warningMessage);
|
||||
}
|
||||
if (cs!=null && cs.getContent() != CodeSystemContentMode.COMPLETE) {
|
||||
warningMessage = "Unable to resolve system "+system+" - system is not complete";
|
||||
if (!inExpansion)
|
||||
throw new FHIRException(warningMessage);
|
||||
}
|
||||
|
||||
if (cs!=null)
|
||||
res = validateCode(code, cs);
|
||||
} else {
|
||||
inExpansion = checkExpansion(code);
|
||||
}
|
||||
|
||||
// then, if we have a value set, we check it's in the value set
|
||||
if ((res==null || res.isOk()) && valueset != null && !codeInValueSet(system, code.getCode())) {
|
||||
if (!inExpansion)
|
||||
res.setMessage("Not in value set "+valueset.getUrl()).setSeverity(IssueSeverity.ERROR);
|
||||
else if (warningMessage!=null)
|
||||
res = new ValidationResult(IssueSeverity.WARNING, "Code found in expansion, however: " + warningMessage);
|
||||
else
|
||||
res.setMessage("Code found in expansion, however: " + res.getMessage());
|
||||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
if ((res==null || res.isOk()) && !codeInValueSet(system, code.getCode())) {
|
||||
if (!inExpansion)
|
||||
res.setMessage("Not in value set "+valueset.getUrl()).setSeverity(IssueSeverity.ERROR);
|
||||
else if (warningMessage!=null)
|
||||
res = new ValidationResult(IssueSeverity.WARNING, "Code found in expansion, however: " + warningMessage);
|
||||
else
|
||||
res.setMessage("Code found in expansion, however: " + res.getMessage());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -27,4 +27,8 @@ public interface ToolingClientLogger {
|
|||
|
||||
public void logRequest(String method, String url, List<String> headers, byte[] body);
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body);
|
||||
public String getLastId();
|
||||
public void clearLastId();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
package org.hl7.fhir.utilities.validation;
|
||||
|
||||
|
||||
public class ValidationOptions {
|
||||
public enum ValueSetMode {
|
||||
ALL_CHECKS, CHECK_MEMERSHIP_ONLY, NO_MEMBERSHIP_CHECK
|
||||
}
|
||||
|
||||
private String language;
|
||||
private boolean useServer = true;
|
||||
private boolean useClient = true;
|
||||
private boolean guessSystem = false;
|
||||
private ValueSetMode valueSetMode = ValueSetMode.ALL_CHECKS;
|
||||
|
||||
public ValidationOptions() {
|
||||
super();
|
||||
|
@ -67,10 +73,28 @@ public class ValidationOptions {
|
|||
|
||||
|
||||
public String toJson() {
|
||||
return "\"lang\":\""+language+"\", \"useServer\":\""+Boolean.toString(useServer)+"\", \"useClient\":\""+Boolean.toString(useClient)+"\", \"guessSystem\":\""+Boolean.toString(guessSystem)+"\"";
|
||||
return "\"lang\":\""+language+"\", \"useServer\":\""+Boolean.toString(useServer)+"\", \"useClient\":\""+Boolean.toString(useClient)+"\", \"guessSystem\":\""+Boolean.toString(guessSystem)+"\", \"valueSetMode\":\""+valueSetMode.toString()+"\"";
|
||||
}
|
||||
|
||||
public static ValidationOptions defaults() {
|
||||
return new ValidationOptions("en-US");
|
||||
}
|
||||
|
||||
public ValidationOptions checkValueSetOnly() {
|
||||
ValidationOptions n = this.copy();
|
||||
n.valueSetMode = ValueSetMode.CHECK_MEMERSHIP_ONLY;
|
||||
return n;
|
||||
}
|
||||
|
||||
public ValidationOptions noCheckValueSetMembership() {
|
||||
ValidationOptions n = this.copy();
|
||||
n.valueSetMode = ValueSetMode.NO_MEMBERSHIP_CHECK;
|
||||
return n;
|
||||
}
|
||||
|
||||
public ValueSetMode getValueSetMode() {
|
||||
return valueSetMode;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -530,7 +530,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
public void addAncestorProfiles(StructureDefinition sd) {
|
||||
if (sd.hasDerivation() && sd.getDerivation().equals(StructureDefinition.TypeDerivationRule.CONSTRAINT)) {
|
||||
if (sd.hasDerivation() && sd.getDerivation() == StructureDefinition.TypeDerivationRule.CONSTRAINT) {
|
||||
StructureDefinition parentSd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
if (parentSd != null && !profiles.containsKey(parentSd)) {
|
||||
ProfileUsage pu = new ProfileUsage(parentSd);
|
||||
|
@ -944,7 +944,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return true; // we don't validate these
|
||||
else {
|
||||
CodeSystem cs = getCodeSystem(system);
|
||||
if (rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, cs != null, "Unknown Code System " + system)) {
|
||||
if (rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, cs != null, "Unknown Code System '" + system+"'")) {
|
||||
ConceptDefinitionComponent def = getCodeDefinition(cs, code);
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, def != null, "Unknown Code (" + system + "#" + code + ")"))
|
||||
return warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, display == null || display.equals(def.getDisplay()), "Display should be '" + def.getDisplay() + "'");
|
||||
|
@ -962,6 +962,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Invalid System URI: "+system+" - cannot use a value set URI as a system");
|
||||
// Lloyd: This error used to prohibit checking for downstream issues, but there are some cases where that checking needs to occur. Please talk to me before changing the code back.
|
||||
}
|
||||
hint(errors, IssueType.UNKNOWN, element.line(), element.col(), path, false, "Code System URI '"+system+"' is unknown so the code cannot be validated");
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -1076,7 +1077,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (!atLeastOneSystemIsSupported && binding.getStrength() == BindingStrength.EXAMPLE) {
|
||||
// ignore this since we can't validate but it doesn't matter..
|
||||
} else {
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang), cc, valueset); // we're going to validate the codings directly
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang).checkValueSetOnly(), cc, valueset); // we're going to validate the codings directly, so only check the valueset
|
||||
if (!vr.isOk()) {
|
||||
bindingsOk = false;
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
|
||||
|
@ -1112,12 +1113,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// to validate, we'll validate that the codes actually exist
|
||||
if (bindingsOk) {
|
||||
for (Coding nextCoding : cc.getCoding()) {
|
||||
String nextCode = nextCoding.getCode();
|
||||
String nextSystem = nextCoding.getSystem();
|
||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang), nextSystem, nextCode, null);
|
||||
if (!vr.isOk()) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Code {0} is not a valid code in code system {1}", nextCode, nextSystem);
|
||||
if (isNotBlank(nextCoding.getCode()) && isNotBlank(nextCoding.getSystem()) && context.supportsSystem(nextCoding.getSystem())) {
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang).noCheckValueSetMembership(), nextCoding, valueset);
|
||||
if (vr.getSeverity() != null) {
|
||||
if (vr.getSeverity() == IssueSeverity.INFORMATION) {
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
} else if (vr.getSeverity() == IssueSeverity.WARNING) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
} else {
|
||||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4335,9 +4340,6 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, String extensionUrl) throws FHIRException, FHIRException, IOException {
|
||||
// element.markValidation(profile, definition);
|
||||
|
||||
if (debug) {
|
||||
System.out.println(" "+stack.getLiteralPath());
|
||||
}
|
||||
// time = System.nanoTime();
|
||||
// check type invariants
|
||||
checkInvariants(hostContext, errors, profile, definition, resource, element, stack, false);
|
||||
|
@ -4376,6 +4378,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
public void checkChild(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition,
|
||||
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl)
|
||||
throws FHIRException, IOException, DefinitionException {
|
||||
|
||||
List<String> profiles = new ArrayList<String>();
|
||||
if (ei.definition != null) {
|
||||
String type = null;
|
||||
|
@ -4446,6 +4449,9 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
}
|
||||
}
|
||||
NodeStack localStack = stack.push(ei.element, ei.count, ei.definition, type == null ? typeDefn : resolveType(type, ei.definition.getType()));
|
||||
if (debug) {
|
||||
System.out.println(" "+localStack.getLiteralPath());
|
||||
}
|
||||
String localStackLiterapPath = localStack.getLiteralPath();
|
||||
String eiPath = ei.path;
|
||||
assert(eiPath.equals(localStackLiterapPath)) : "ei.path: " + ei.path + " - localStack.getLiteralPath: " + localStackLiterapPath;
|
||||
|
|
|
@ -276,6 +276,11 @@ public class Validator {
|
|||
System.out.println("Specified destination (-dest parameter) is not valid: \""+dest+"\")");
|
||||
else {
|
||||
// first, prepare the context
|
||||
String txLog = null;
|
||||
if (hasParam(args, "-txLog")) {
|
||||
txLog = getParam(args, "-txLog");
|
||||
new File(txLog).delete();
|
||||
}
|
||||
String v = getParam(args, "-version");
|
||||
if (v == null) {
|
||||
v = "current";
|
||||
|
@ -314,7 +319,7 @@ public class Validator {
|
|||
}
|
||||
String definitions = VersionUtilities.packageForVersion(v)+"#"+v;
|
||||
System.out.println("Loading (v = "+v+", tx server http://tx.fhir.org)");
|
||||
ValidationEngine validator = new ValidationEngine(definitions, "http://tx.fhir.org", null, FhirPublication.fromCode(v));
|
||||
ValidationEngine validator = new ValidationEngine(definitions, "http://tx.fhir.org", txLog, FhirPublication.fromCode(v));
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if ("-ig".equals(args[i])) {
|
||||
if (i+1 == args.length)
|
||||
|
|
|
@ -129,7 +129,7 @@ public class ValidationEngineTests {
|
|||
int h = hints(op);
|
||||
Assert.assertTrue(e == 1);
|
||||
Assert.assertTrue(w == 0);
|
||||
Assert.assertTrue(h == 0);
|
||||
Assert.assertTrue(h == 1);
|
||||
if (!TestUtilities.silent)
|
||||
System.out.println(" .. done: "+Integer.toString(e)+" errors, "+Integer.toString(w)+" warnings, "+Integer.toString(h)+" information messages");
|
||||
}
|
||||
|
|
|
@ -93,23 +93,28 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
@Test
|
||||
public void test() throws Exception {
|
||||
System.out.println("Name: " + name+" - base");
|
||||
String txLog = null;
|
||||
if (content.has("txLog")) {
|
||||
txLog = content.get("txLog").getAsString();
|
||||
}
|
||||
String v = "5.0";
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (content.has("version"))
|
||||
if (content.has("version")) {
|
||||
v = content.get("version").getAsString();
|
||||
}
|
||||
|
||||
v = VersionUtilities.getMajMin(v);
|
||||
if (!ve.containsKey(v)) {
|
||||
if (v.startsWith("5.0"))
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r5.core#current", DEF_TX, null, FhirPublication.R5, true));
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r5.core#current", DEF_TX, txLog, FhirPublication.R5, true));
|
||||
else if (v.startsWith("3.0"))
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, true));
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, txLog, FhirPublication.STU3, true));
|
||||
else if (v.startsWith("4.0"))
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, true));
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, txLog, FhirPublication.R4, true));
|
||||
else if (v.startsWith("1.0"))
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, true));
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, txLog, FhirPublication.DSTU2, true));
|
||||
else if (v.startsWith("1.4"))
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, null, FhirPublication.DSTU2016May, true));
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, txLog, FhirPublication.DSTU2016May, true));
|
||||
else
|
||||
throw new Exception("unknown version "+v);
|
||||
}
|
||||
|
@ -155,6 +160,11 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
}
|
||||
}
|
||||
List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
|
||||
if (content.getAsJsonObject("java").has("debug")) {
|
||||
val.setDebug(content.getAsJsonObject("java").get("debug").getAsBoolean());
|
||||
} else {
|
||||
val.setDebug(false);
|
||||
}
|
||||
if (name.endsWith(".json"))
|
||||
val.validate(null, errors, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON);
|
||||
else
|
||||
|
@ -277,7 +287,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
}
|
||||
if (vm.getLevel() == IssueSeverity.INFORMATION) {
|
||||
hc++;
|
||||
if (java.has("infoCount")) {
|
||||
if (java.has("infoCount") || java.has("debug")) {
|
||||
System.out.println("hint: "+vm.getDisplay());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue