Support displayLanguage through validator framework
This commit is contained in:
parent
4ff9e0626a
commit
23eb7282bd
|
@ -82,6 +82,7 @@ import org.hl7.fhir.r5.model.UriType;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -215,6 +216,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
private ProfileKnowledgeProvider pkp;
|
||||
private boolean igmode;
|
||||
private boolean exception;
|
||||
private TerminologyServiceOptions terminologyServiceOptions = new TerminologyServiceOptions();
|
||||
|
||||
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp) {
|
||||
super();
|
||||
|
@ -2787,13 +2789,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
private Piece describeCoded(HierarchicalTableGenerator gen, Type fixed) {
|
||||
if (fixed instanceof Coding) {
|
||||
Coding c = (Coding) fixed;
|
||||
ValidationResult vr = context.validateCode(c.getSystem(), c.getCode(), c.getDisplay());
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions , c.getSystem(), c.getCode(), c.getDisplay());
|
||||
if (vr.getDisplay() != null)
|
||||
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
||||
} else if (fixed instanceof CodeableConcept) {
|
||||
CodeableConcept cc = (CodeableConcept) fixed;
|
||||
for (Coding c : cc.getCoding()) {
|
||||
ValidationResult vr = context.validateCode(c.getSystem(), c.getCode(), c.getDisplay());
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions, c.getSystem(), c.getCode(), c.getDisplay());
|
||||
if (vr.getDisplay() != null)
|
||||
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
||||
}
|
||||
|
@ -4236,4 +4238,16 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
public void setThrowException(boolean exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
|
||||
public TerminologyServiceOptions getTerminologyServiceOptions() {
|
||||
return terminologyServiceOptions;
|
||||
}
|
||||
|
||||
|
||||
public void setTerminologyServiceOptions(TerminologyServiceOptions terminologyServiceOptions) {
|
||||
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
|
@ -458,39 +459,39 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
// --- validate code -------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(String system, String code, String display) {
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display) {
|
||||
Coding c = new Coding(system, code, display);
|
||||
return validateCode(c, null);
|
||||
return validateCode(options, c, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(String system, String code, String display, ValueSet vs) {
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display, ValueSet vs) {
|
||||
Coding c = new Coding(system, code, display);
|
||||
return validateCode(c, vs);
|
||||
return validateCode(options, c, vs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(String code, ValueSet vs) {
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String code, ValueSet vs) {
|
||||
Coding c = new Coding(null, code, null);
|
||||
return doValidateCode(c, vs, true);
|
||||
return doValidateCode(options, c, vs, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(String system, String code, String display, ConceptSetComponent vsi) {
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display, ConceptSetComponent vsi) {
|
||||
Coding c = new Coding(system, code, display);
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(Utilities.makeUuidUrn());
|
||||
vs.getCompose().addInclude(vsi);
|
||||
return validateCode(c, vs);
|
||||
return validateCode(options, c, vs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(Coding code, ValueSet vs) {
|
||||
return doValidateCode(code, vs, false);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, Coding code, ValueSet vs) {
|
||||
return doValidateCode(options, code, vs, false);
|
||||
}
|
||||
|
||||
public ValidationResult doValidateCode(Coding code, ValueSet vs, boolean implySystem) {
|
||||
CacheToken cacheToken = txCache != null ? txCache.generateValidationToken(code, vs) : null;
|
||||
public ValidationResult doValidateCode(TerminologyServiceOptions options, Coding code, ValueSet vs, boolean implySystem) {
|
||||
CacheToken cacheToken = txCache != null ? txCache.generateValidationToken(options, code, vs) : null;
|
||||
ValidationResult res = null;
|
||||
if (txCache != null)
|
||||
res = txCache.getValidation(cacheToken);
|
||||
|
@ -499,7 +500,7 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
|
||||
// ok, first we try to validate locally
|
||||
try {
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(vs, this);
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, this);
|
||||
res = vsc.validateCode(code);
|
||||
if (txCache != null)
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
|
@ -520,6 +521,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
pIn.addParameter().setName("coding").setValue(code);
|
||||
if (implySystem)
|
||||
pIn.addParameter().setName("implySystem").setValue(new BooleanType(true));
|
||||
if (options != null)
|
||||
options.updateParameters(pIn);
|
||||
res = validateOnServer(vs, pIn);
|
||||
} catch (Exception e) {
|
||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog == null ? null : txLog.getLastId());
|
||||
|
@ -530,15 +533,15 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(CodeableConcept code, ValueSet vs) {
|
||||
CacheToken cacheToken = txCache.generateValidationToken(code, vs);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, CodeableConcept code, ValueSet vs) {
|
||||
CacheToken cacheToken = txCache.generateValidationToken(options, code, vs);
|
||||
ValidationResult res = txCache.getValidation(cacheToken);
|
||||
if (res != null)
|
||||
return res;
|
||||
|
||||
// ok, first we try to validate locally
|
||||
try {
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(vs, this);
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, this);
|
||||
res = vsc.validateCode(code);
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
return res;
|
||||
|
@ -552,6 +555,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
try {
|
||||
Parameters pIn = new Parameters();
|
||||
pIn.addParameter().setName("codeableConcept").setValue(code);
|
||||
if (options != null)
|
||||
options.updateParameters(pIn);
|
||||
res = validateOnServer(vs, pIn);
|
||||
} catch (Exception e) {
|
||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog.getLastId());
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
|||
import org.hl7.fhir.r5.model.StructureMap;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.INarrativeGenerator;
|
||||
|
@ -371,7 +372,7 @@ public interface IWorkerContext {
|
|||
* @param display
|
||||
* @return
|
||||
*/
|
||||
public ValidationResult validateCode(String system, String code, String display);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display);
|
||||
|
||||
/**
|
||||
* Validation of a code - consult the terminology service
|
||||
|
@ -387,10 +388,10 @@ public interface IWorkerContext {
|
|||
* @param display
|
||||
* @return
|
||||
*/
|
||||
public ValidationResult validateCode(String system, String code, String display, ValueSet vs);
|
||||
public ValidationResult validateCode(String code, ValueSet vs);
|
||||
public ValidationResult validateCode(Coding code, ValueSet vs);
|
||||
public ValidationResult validateCode(CodeableConcept code, ValueSet vs);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display, ValueSet vs);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String code, ValueSet vs);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, Coding code, ValueSet vs);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, CodeableConcept code, ValueSet vs);
|
||||
|
||||
/**
|
||||
* Validation of a code - consult the terminology service
|
||||
|
@ -406,7 +407,7 @@ public interface IWorkerContext {
|
|||
* @param display
|
||||
* @return
|
||||
*/
|
||||
public ValidationResult validateCode(String system, String code, String display, ConceptSetComponent vsi);
|
||||
public ValidationResult validateCode(TerminologyServiceOptions options, String system, String code, String display, ConceptSetComponent vsi);
|
||||
|
||||
/**
|
||||
* returns the recommended tla for the type
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
@ -111,7 +112,7 @@ public class TerminologyCache {
|
|||
load();
|
||||
}
|
||||
|
||||
public CacheToken generateValidationToken(Coding code, ValueSet vs) {
|
||||
public CacheToken generateValidationToken(TerminologyServiceOptions options, Coding code, ValueSet vs) {
|
||||
CacheToken ct = new CacheToken();
|
||||
if (code.hasSystem())
|
||||
ct.name = getNameForSystem(code.getSystem());
|
||||
|
@ -121,7 +122,7 @@ public class TerminologyCache {
|
|||
json.setOutputStyle(OutputStyle.PRETTY);
|
||||
ValueSet vsc = getVSEssense(vs);
|
||||
try {
|
||||
ct.request = "{\"code\" : "+json.composeString(code, "code")+", \"valueSet\" :"+(vsc == null ? "null" : json.composeString(vsc))+"}";
|
||||
ct.request = "{\"code\" : "+json.composeString(code, "code")+", \"valueSet\" :"+(vsc == null ? "null" : json.composeString(vsc))+(options == null ? "" : ", "+options.toJson())+"}";
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ public class TerminologyCache {
|
|||
return ct;
|
||||
}
|
||||
|
||||
public CacheToken generateValidationToken(CodeableConcept code, ValueSet vs) {
|
||||
public CacheToken generateValidationToken(TerminologyServiceOptions options, CodeableConcept code, ValueSet vs) {
|
||||
CacheToken ct = new CacheToken();
|
||||
for (Coding c : code.getCoding()) {
|
||||
if (c.hasSystem())
|
||||
|
@ -139,7 +140,7 @@ public class TerminologyCache {
|
|||
json.setOutputStyle(OutputStyle.PRETTY);
|
||||
ValueSet vsc = getVSEssense(vs);
|
||||
try {
|
||||
ct.request = "{\"code\" : "+json.composeString(code, "codeableConcept")+", \"valueSet\" :"+json.composeString(vsc)+"}";
|
||||
ct.request = "{\"code\" : "+json.composeString(code, "codeableConcept")+", \"valueSet\" :"+json.composeString(vsc)+(options == null ? "" : ", "+options.toJson())+"}";
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import org.fhir.ucum.Utilities;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
|
||||
public class TerminologyServiceOptions {
|
||||
private String language;
|
||||
|
||||
public TerminologyServiceOptions() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TerminologyServiceOptions(String language) {
|
||||
super();
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return "\"lang\":\""+language+"\"";
|
||||
}
|
||||
|
||||
public void updateParameters(Parameters pIn) {
|
||||
if (!Utilities.noString(language))
|
||||
pIn.addParameter("displayLanguage", language);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -51,10 +51,12 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
|
|||
private ValueSet valueset;
|
||||
private IWorkerContext context;
|
||||
private Map<String, ValueSetCheckerSimple> inner = new HashMap<>();
|
||||
private TerminologyServiceOptions options;
|
||||
|
||||
public ValueSetCheckerSimple(ValueSet source, IWorkerContext context) {
|
||||
public ValueSetCheckerSimple(TerminologyServiceOptions options, ValueSet source, IWorkerContext context) {
|
||||
this.valueset = source;
|
||||
this.context = context;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public ValidationResult validateCode(CodeableConcept code) throws FHIRException {
|
||||
|
@ -425,7 +427,7 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
|
|||
return inner.get(url);
|
||||
}
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, url);
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(vs, context);
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, context);
|
||||
inner.put(url, vsc);
|
||||
return vsc;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.hl7.fhir.r5.model.TemporalPrecisionEnum;
|
|||
import org.hl7.fhir.r5.model.TimeType;
|
||||
import org.hl7.fhir.r5.model.TypeDetails;
|
||||
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
|
||||
|
@ -175,6 +176,7 @@ public class FHIRPathEngine {
|
|||
private Set<String> primitiveTypes = new HashSet<String>();
|
||||
private Map<String, StructureDefinition> allTypes = new HashMap<String, StructureDefinition>();
|
||||
private boolean legacyMode; // some R2 and R3 constraints assume that != is valid for emptty sets, so when running for R2/R3, this is set ot true
|
||||
private TerminologyServiceOptions terminologyServiceOptions = new TerminologyServiceOptions();
|
||||
|
||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||
// the application can implement them by providing a constant resolver
|
||||
|
@ -1893,13 +1895,13 @@ public class FHIRPathEngine {
|
|||
if (vs != null) {
|
||||
for (Base l : left) {
|
||||
if (l.fhirType().equals("code")) {
|
||||
if (worker.validateCode(l.castToCoding(l), vs).isOk())
|
||||
if (worker.validateCode(terminologyServiceOptions , l.castToCoding(l), vs).isOk())
|
||||
ans = true;
|
||||
} else if (l.fhirType().equals("Coding")) {
|
||||
if (worker.validateCode(l.castToCoding(l), vs).isOk())
|
||||
if (worker.validateCode(terminologyServiceOptions, l.castToCoding(l), vs).isOk())
|
||||
ans = true;
|
||||
} else if (l.fhirType().equals("CodeableConcept")) {
|
||||
if (worker.validateCode(l.castToCodeableConcept(l), vs).isOk())
|
||||
if (worker.validateCode(terminologyServiceOptions, l.castToCodeableConcept(l), vs).isOk())
|
||||
ans = true;
|
||||
}
|
||||
}
|
||||
|
@ -4306,5 +4308,10 @@ public class FHIRPathEngine {
|
|||
private Equality boolToTriState(boolean b) {
|
||||
return b ? Equality.True : Equality.False;
|
||||
}
|
||||
|
||||
|
||||
public TerminologyServiceOptions getTerminologyServiceOptions() {
|
||||
return terminologyServiceOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -133,6 +133,9 @@ public interface IResourceValidator {
|
|||
public boolean isErrorForUnknownProfiles();
|
||||
public void setErrorForUnknownProfiles(boolean errorForUnknownProfiles);
|
||||
|
||||
public String getValidationLanguage();
|
||||
public void setValidationLanguage(String value);
|
||||
|
||||
/**
|
||||
* Validate suite
|
||||
*
|
||||
|
|
|
@ -175,6 +175,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
||||
|
@ -999,6 +1000,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
|
||||
private boolean pretty;
|
||||
private boolean canonicalUrlsAsLinks;
|
||||
private TerminologyServiceOptions terminologyServiceOptions = new TerminologyServiceOptions();
|
||||
|
||||
public NarrativeGenerator(String prefix, String basePath, IWorkerContext context) {
|
||||
super();
|
||||
|
@ -1836,7 +1838,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
}
|
||||
|
||||
private String lookupCode(String system, String code) {
|
||||
ValidationResult t = context.validateCode(system, code, null);
|
||||
ValidationResult t = context.validateCode(terminologyServiceOptions , system, code, null);
|
||||
|
||||
if (t != null && t.getDisplay() != null)
|
||||
return t.getDisplay();
|
||||
|
@ -2568,7 +2570,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
private String getDisplayForConcept(String system, String value) {
|
||||
if (value == null || system == null)
|
||||
return null;
|
||||
ValidationResult cl = context.validateCode(system, value, null);
|
||||
ValidationResult cl = context.validateCode(terminologyServiceOptions, system, value, null);
|
||||
return cl == null ? null : cl.getDisplay();
|
||||
}
|
||||
|
||||
|
@ -3765,7 +3767,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
li.ah(href).addText(f.getValue());
|
||||
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
||||
li.addText(f.getValue());
|
||||
ValidationResult vr = context.validateCode(inc.getSystem(), f.getValue(), null);
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions, inc.getSystem(), f.getValue(), null);
|
||||
if (vr.isOk()) {
|
||||
li.tx(" ("+vr.getDisplay()+")");
|
||||
}
|
||||
|
@ -3847,7 +3849,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
return context.validateCode(inc.getSystem(), code, null).asConceptDefinition();
|
||||
return context.validateCode(terminologyServiceOptions, inc.getSystem(), code, null).asConceptDefinition();
|
||||
}
|
||||
|
||||
|
||||
|
@ -4752,5 +4754,13 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TerminologyServiceOptions getTerminologyServiceOptions() {
|
||||
return terminologyServiceOptions;
|
||||
}
|
||||
|
||||
public void setTerminologyServiceOptions(TerminologyServiceOptions terminologyServiceOptions) {
|
||||
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
|||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
|
@ -221,7 +222,8 @@ public class StructureMapUtilities {
|
|||
private FHIRPathEngine fpe;
|
||||
private ITransformerServices services;
|
||||
private ProfileKnowledgeProvider pkp;
|
||||
private Map<String, Integer> ids = new HashMap<String, Integer>();
|
||||
private Map<String, Integer> ids = new HashMap<String, Integer>();
|
||||
private TerminologyServiceOptions terminologyServiceOptions = new TerminologyServiceOptions();
|
||||
|
||||
public StructureMapUtilities(IWorkerContext worker, ITransformerServices services, ProfileKnowledgeProvider pkp) {
|
||||
super();
|
||||
|
@ -1965,7 +1967,7 @@ public class StructureMapUtilities {
|
|||
throw new FHIRException("The code '"+code+"' is not in the value set '"+uri+"' (valid codes: "+b.toString()+"; also checked displays)");
|
||||
} else
|
||||
system = uri;
|
||||
ValidationResult vr = worker.validateCode(system, code, null);
|
||||
ValidationResult vr = worker.validateCode(terminologyServiceOptions, system, code, null);
|
||||
if (vr != null && vr.getDisplay() != null)
|
||||
display = vr.getDisplay();
|
||||
return new Coding().setSystem(system).setCode(code).setDisplay(display);
|
||||
|
@ -2958,5 +2960,13 @@ public class StructureMapUtilities {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TerminologyServiceOptions getTerminologyServiceOptions() {
|
||||
return terminologyServiceOptions;
|
||||
}
|
||||
|
||||
public void setTerminologyServiceOptions(TerminologyServiceOptions terminologyServiceOptions) {
|
||||
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
|
@ -121,6 +122,7 @@ import org.hl7.fhir.r5.model.TypeDetails;
|
|||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
|
@ -264,6 +266,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private boolean noTerminologyChecks;
|
||||
private boolean hintAboutNonMustSupport;
|
||||
private BestPracticeWarningLevel bpWarnings;
|
||||
private String validationLanguage;
|
||||
|
||||
private List<String> extensionDomains = new ArrayList<String>();
|
||||
|
||||
|
@ -821,13 +824,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
// public API
|
||||
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String display, boolean checkDisplay) throws TerminologyServiceException {
|
||||
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String display, boolean checkDisplay, NodeStack stack) throws TerminologyServiceException {
|
||||
long t = System.nanoTime();
|
||||
boolean ss = context.supportsSystem(system);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (ss) {
|
||||
t = System.nanoTime();
|
||||
ValidationResult s = context.validateCode(system, code, checkDisplay ? display : null);
|
||||
ValidationResult s = context.validateCode(new TerminologyServiceOptions(stack.workingLang), system, code, checkDisplay ? display : null);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (s == null)
|
||||
return true;
|
||||
|
@ -935,7 +938,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
private boolean checkCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext) {
|
||||
private boolean checkCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, NodeStack stack) {
|
||||
boolean res = true;
|
||||
if (!noTerminologyChecks && theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
|
@ -968,7 +971,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(cc, valueset);
|
||||
ValidationResult vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), cc, valueset);
|
||||
res = false;
|
||||
if (!vr.isOk()) {
|
||||
bindingsOk = false;
|
||||
|
@ -977,7 +980,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " and a code from this value set is required (class = "+vr.getErrorClass().toString()+")");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc);
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " and a code should come from this value set unless it has no suitable code (class = "+vr.getErrorClass().toString()+")");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
|
@ -987,7 +990,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "None of the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl()+", and a code from this value set is required) (codes = "+ccSummary(cc)+")");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc);
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "None of the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code) (codes = "+ccSummary(cc)+")");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
|
@ -1003,7 +1006,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
String nextCode = nextCoding.getCode();
|
||||
String nextSystem = nextCoding.getSystem();
|
||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
ValidationResult vr = context.validateCode(nextSystem, nextCode, null);
|
||||
ValidationResult vr = context.validateCode(new TerminologyServiceOptions(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);
|
||||
}
|
||||
|
@ -1027,13 +1030,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return res;
|
||||
}
|
||||
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc) {
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc, NodeStack stack) {
|
||||
// TODO Auto-generated method stub
|
||||
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, "ValueSet " + describeReference(maxVSUrl) + " not found")) {
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = context.validateCode(cc, valueset);
|
||||
ValidationResult vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), cc, valueset);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1047,13 +1050,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, Coding c) {
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, Coding c, NodeStack stack) {
|
||||
// TODO Auto-generated method stub
|
||||
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, "ValueSet " + describeReference(maxVSUrl) + " not found")) {
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = context.validateCode(c, valueset);
|
||||
ValidationResult vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), c, valueset);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1067,13 +1070,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, String value) {
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, String value, NodeStack stack) {
|
||||
// TODO Auto-generated method stub
|
||||
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, "ValueSet " + describeReference(maxVSUrl) + " not found")) {
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = context.validateCode(value, valueset);
|
||||
ValidationResult vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), value, valueset);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1101,7 +1104,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
checkFixedValue(errors, path + ".userSelected", focus.getNamedChild("userSelected"), fixed.getUserSelectedElement(), "userSelected", focus);
|
||||
}
|
||||
|
||||
private void checkCoding(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay) {
|
||||
private void checkCoding(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay, NodeStack stack) {
|
||||
String code = element.getNamedChildValue("code");
|
||||
String system = element.getNamedChildValue("system");
|
||||
String display = element.getNamedChildValue("display");
|
||||
|
@ -1110,7 +1113,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (system != null && code != null && !noTerminologyChecks) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), "The Coding references a value set, not a code system (\""+system+"\")");
|
||||
try {
|
||||
if (checkCode(errors, element, path, code, system, display, checkDisplay))
|
||||
if (checkCode(errors, element, path, code, system, display, checkDisplay, stack))
|
||||
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, "Binding for " + path + " missing")) {
|
||||
|
@ -1122,7 +1125,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
long t = System.nanoTime();
|
||||
ValidationResult vr = null;
|
||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
vr = context.validateCode(c, valueset);
|
||||
vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), c, valueset);
|
||||
}
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (vr != null && !vr.isOk()) {
|
||||
|
@ -1133,7 +1136,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl()+", and a code from this value set is required)");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c);
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code)");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
|
@ -1142,7 +1145,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The Coding provided is not in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code is required from this value set)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c);
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
|
||||
else
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The Coding provided is not in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
|
@ -1495,7 +1498,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
checkFixedValue(errors, path + ".end", focus.getNamedChild("end"), fixed.getEndElement(), "end", focus);
|
||||
}
|
||||
|
||||
private void checkPrimitive(Object appContext, List<ValidationMessage> errors, String path, String type, ElementDefinition context, Element e, StructureDefinition profile) throws FHIRException, IOException {
|
||||
private void checkPrimitive(Object appContext, List<ValidationMessage> errors, String path, String type, ElementDefinition context, Element e, StructureDefinition profile, NodeStack node) throws FHIRException, IOException {
|
||||
if (isBlank(e.primitiveValue())) {
|
||||
if (e.primitiveValue() == null)
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, e.hasChildren(), "Primitive types must have a value or must have child extensions");
|
||||
|
@ -1663,7 +1666,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
if (context.hasBinding() && e.primitiveValue() != null) {
|
||||
checkPrimitiveBinding(errors, path, type, context, e, profile);
|
||||
checkPrimitiveBinding(errors, path, type, context, e, profile, node);
|
||||
}
|
||||
|
||||
if (type.equals("xhtml")) {
|
||||
|
@ -1730,7 +1733,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
private void checkPrimitiveBinding(List<ValidationMessage> errors, String path, String type, ElementDefinition elementContext, Element element, StructureDefinition profile) {
|
||||
private void checkPrimitiveBinding(List<ValidationMessage> errors, String path, String type, ElementDefinition elementContext, Element element, StructureDefinition profile, NodeStack stack) {
|
||||
// We ignore bindings that aren't on string, uri or code
|
||||
if (!element.hasPrimitiveValue() || !("code".equals(type) || "string".equals(type) || "uri".equals(type) || "url".equals(type) || "canonical".equals(type))) {
|
||||
return;
|
||||
|
@ -1749,7 +1752,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
long t = System.nanoTime();
|
||||
ValidationResult vr = null;
|
||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
vr = context.validateCode(value, vs);
|
||||
vr = context.validateCode(new TerminologyServiceOptions(stack.workingLang), value, vs);
|
||||
}
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (vr != null && !vr.isOk()) {
|
||||
|
@ -1759,7 +1762,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code is required from this value set)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), value);
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), value, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code should come from this value set unless it has no suitable code)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
|
@ -2862,6 +2865,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// the instance at root is valid against the schema and schematron
|
||||
// the instance validator had no issues against the base resource profile
|
||||
private void start(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack) throws FHIRException, FHIRException, IOException {
|
||||
checkLang(resource, stack);
|
||||
|
||||
// profile is valid, and matches the resource name
|
||||
ResourceProfiles resourceProfiles = getResourceProfiles(element, stack);
|
||||
if (!resourceProfiles.isProcessed())
|
||||
|
@ -2896,6 +2901,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
private void checkLang(Element resource, NodeStack stack) {
|
||||
String lang = resource.getNamedChildValue("language");
|
||||
if (!Utilities.noString(lang))
|
||||
stack.workingLang = lang;
|
||||
}
|
||||
|
||||
private void validateResourceRules(List<ValidationMessage> errors, Element element, NodeStack stack) {
|
||||
String lang = element.getNamedChildValue("language");
|
||||
Element text = element.getNamedChild("text");
|
||||
|
@ -3256,7 +3267,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
}
|
||||
|
||||
long t = System.nanoTime();
|
||||
ValidationResult res = context.validateCode(c, vs);
|
||||
ValidationResult res = context.validateCode(new TerminologyServiceOptions(stack.workingLang), c, vs);
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (!res.isOk()) {
|
||||
txRule(errors, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, "The value provided (" + c.getSystem() + "::" + c.getCode() + ") is not in the options value set in the questionnaire");
|
||||
|
@ -3968,7 +3979,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
ei.element.markValidation(profile, ei.definition);
|
||||
if (type != null) {
|
||||
if (isPrimitiveType(type)) {
|
||||
checkPrimitive(hostContext, errors, ei.path, type, ei.definition, ei.element, profile);
|
||||
checkPrimitive(hostContext, errors, ei.path, type, ei.definition, ei.element, profile, stack);
|
||||
} else {
|
||||
if (ei.definition.hasFixed()) {
|
||||
checkFixedValue(errors,ei.path, ei.element, ei.definition.getFixed(), ei.definition.getSliceName(), null);
|
||||
|
@ -3980,9 +3991,9 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
if (type.equals("Identifier")) {
|
||||
checkIdentifier(errors, ei.path, ei.element, ei.definition);
|
||||
} else if (type.equals("Coding")) {
|
||||
checkCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept, checkDisplayInContext);
|
||||
checkCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept, checkDisplayInContext, stack);
|
||||
} else if (type.equals("CodeableConcept")) {
|
||||
checkDisplay = checkCodeableConcept(errors, ei.path, ei.element, profile, ei.definition);
|
||||
checkDisplay = checkCodeableConcept(errors, ei.path, ei.element, profile, ei.definition, stack);
|
||||
thisIsCodeableConcept = true;
|
||||
} else if (type.equals("Reference")) {
|
||||
checkReference(hostContext, errors, ei.path, ei.element, profile, ei.definition, actualType, localStack);
|
||||
|
@ -4423,13 +4434,16 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
private List<String> logicalPaths; // dotted format, various entry points
|
||||
private NodeStack parent;
|
||||
private ElementDefinition type;
|
||||
private String workingLang;
|
||||
|
||||
public NodeStack() {
|
||||
workingLang = validationLanguage;
|
||||
}
|
||||
|
||||
public NodeStack(Element element) {
|
||||
this.element = element;
|
||||
literalPath = element.getName();
|
||||
workingLang = validationLanguage;
|
||||
}
|
||||
|
||||
public String addToLiteralPath(String... path) {
|
||||
|
@ -4471,6 +4485,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
private NodeStack push(Element element, int count, ElementDefinition definition, ElementDefinition type) {
|
||||
NodeStack res = new NodeStack();
|
||||
res.parent = this;
|
||||
res.workingLang = this.workingLang;
|
||||
res.element = element;
|
||||
res.definition = definition;
|
||||
res.literalPath = getLiteralPath() + "." + element.getName();
|
||||
|
@ -4632,5 +4647,13 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
return externalHostServices;
|
||||
}
|
||||
|
||||
public String getValidationLanguage() {
|
||||
return validationLanguage;
|
||||
}
|
||||
|
||||
public void setValidationLanguage(String validationLanguage) {
|
||||
this.validationLanguage = validationLanguage;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -244,6 +244,7 @@ public class ValidationEngine {
|
|||
private boolean hintAboutNonMustSupport;
|
||||
private boolean anyExtensionsAllowed = false;
|
||||
private String version;
|
||||
private String language;
|
||||
private PackageCacheManager pcm;
|
||||
private PrintWriter mapLog;
|
||||
|
||||
|
@ -323,6 +324,14 @@ public class ValidationEngine {
|
|||
pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
private void loadDefinitions(String src) throws Exception {
|
||||
Map<String, byte[]> source = loadIgSource(src);
|
||||
if (version == null)
|
||||
|
@ -1062,6 +1071,7 @@ public class ValidationEngine {
|
|||
validator.setHintAboutNonMustSupport(hintAboutNonMustSupport);
|
||||
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
||||
validator.setNoInvariantChecks(isNoInvariantChecks());
|
||||
validator.setValidationLanguage(language);
|
||||
return validator;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,10 @@ public class Validator {
|
|||
System.out.println(" * JSON: json.schema");
|
||||
System.out.println(" * RDF: SHEX");
|
||||
System.out.println(" Default: false");
|
||||
System.out.println("-language: [lang]");
|
||||
System.out.println(" The language to use when validating coding displays - same value as for xml:lang");
|
||||
System.out.println(" Not used if the resource specifies language");
|
||||
System.out.println(" Default: no specified language");
|
||||
System.out.println("-strictExtensions: If present, treat extensions not defined within the specified FHIR version and any");
|
||||
System.out.println(" referenced implementation guides or profiles as errors. (Default is to only raise information messages.)");
|
||||
System.out.println("-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not");
|
||||
|
@ -269,6 +273,7 @@ public class Validator {
|
|||
String sv = null;
|
||||
String txLog = null;
|
||||
String mapLog = null;
|
||||
String lang = null;
|
||||
|
||||
// load the parameters - so order doesn't matter
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
@ -337,6 +342,11 @@ public class Validator {
|
|||
throw new Error("Specified -log without indicating file");
|
||||
else
|
||||
mapLog = args[++i];
|
||||
else if (args[i].equals("-language"))
|
||||
if (i+1 == args.length)
|
||||
throw new Error("Specified -language without indicating language");
|
||||
else
|
||||
lang = args[++i];
|
||||
else if (args[i].equals("-ig"))
|
||||
if (i+1 == args.length)
|
||||
throw new Error("Specified -ig without indicating ig file");
|
||||
|
@ -378,6 +388,7 @@ public class Validator {
|
|||
validator.setNative(doNative);
|
||||
validator.setHintAboutNonMustSupport(hintAboutNonMustSupport);
|
||||
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
||||
validator.setLanguage(lang);
|
||||
|
||||
IParser x;
|
||||
if (output != null && output.endsWith(".json"))
|
||||
|
|
|
@ -94,8 +94,8 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
this.content = content;
|
||||
}
|
||||
|
||||
private static final String DEF_TX = "http://tx.fhir.org";
|
||||
private static final String DBG_TX = "http://local.fhir.org:960";
|
||||
// private static final String DEF_TX = "http://tx.fhir.org";
|
||||
private static final String DEF_TX = "http://local.fhir.org:960";
|
||||
private static ValidationEngine ve;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -133,6 +133,10 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
if (content.has("allowed-extension-domains"))
|
||||
for (JsonElement a : content.getAsJsonArray("allowed-extension-domains"))
|
||||
val.getExtensionDomains().add(a.getAsString());
|
||||
if (content.has("language"))
|
||||
val.setValidationLanguage(content.get("language").getAsString());
|
||||
else
|
||||
val.setValidationLanguage(null);
|
||||
val.setFetcher(this);
|
||||
if (content.has("questionnaire")) {
|
||||
ve.getContext().cacheResource(loadResource(TestUtilities.resourceNameToFile("validation-examples", content.get("questionnaire").getAsString()), v));
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Observation xmlns="http://hl7.org/fhir">
|
||||
<status value="final"/>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org" />
|
||||
<code value="3151-8"/>
|
||||
<display value="ingeademde O2" />
|
||||
</coding>
|
||||
</code>
|
||||
<subject>
|
||||
<reference value="Patient/example" />
|
||||
<display value="Example Patient" />
|
||||
</subject>
|
||||
<effectiveDateTime value="2016-12-19T09:00:00Z" />
|
||||
<valueQuantity>
|
||||
<value value="8"/>
|
||||
</valueQuantity>
|
||||
</Observation>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Observation xmlns="http://hl7.org/fhir">
|
||||
<status value="final"/>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org" />
|
||||
<code value="3151-8"/>
|
||||
<display value="ingeademde O2" />
|
||||
</coding>
|
||||
</code>
|
||||
<subject>
|
||||
<reference value="Patient/example" />
|
||||
<display value="Example Patient" />
|
||||
</subject>
|
||||
<effectiveDateTime value="2016-12-19T09:00:00Z" />
|
||||
<valueQuantity>
|
||||
<value value="8"/>
|
||||
</valueQuantity>
|
||||
</Observation>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Observation xmlns="http://hl7.org/fhir">
|
||||
<language value="nl-NL"/>
|
||||
<status value="final"/>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org" />
|
||||
<code value="3151-8"/>
|
||||
<display value="ingeademde O2" />
|
||||
</coding>
|
||||
</code>
|
||||
<subject>
|
||||
<reference value="Patient/example" />
|
||||
<display value="Example Patient" />
|
||||
</subject>
|
||||
<effectiveDateTime value="2016-12-19T09:00:00Z" />
|
||||
<valueQuantity>
|
||||
<value value="8"/>
|
||||
</valueQuantity>
|
||||
</Observation>
|
|
@ -176,7 +176,7 @@
|
|||
}
|
||||
},
|
||||
"medication-atc.json": {
|
||||
"errorCount": 1,
|
||||
"errorCount": 0,
|
||||
"allowed-extension-domain": "https://api-v8-r4.hspconsortium.org/DrugFormulary0/open"
|
||||
},
|
||||
"bp.json": {
|
||||
|
@ -768,7 +768,20 @@
|
|||
},
|
||||
"bad-bundle-reference-type.xml": {
|
||||
"errorCount": 1
|
||||
}
|
||||
},
|
||||
"loinc-lang-nl-1.xml" : {
|
||||
"errorCount": 0,
|
||||
"warningCount": 1
|
||||
},
|
||||
"loinc-lang-nl-2.xml" : {
|
||||
"language" : "nl-NL",
|
||||
"errorCount": 0,
|
||||
"warningCount": 0
|
||||
},
|
||||
"loinc-lang-nl-3.xml" : {
|
||||
"errorCount": 0,
|
||||
"warningCount": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue