fix terminology version management and caching + better error messages for extension context
This commit is contained in:
parent
0ca2a6738e
commit
e21a9830b8
|
@ -4887,13 +4887,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
private Piece describeCoded(HierarchicalTableGenerator gen, DataType fixed) {
|
||||
if (fixed instanceof Coding) {
|
||||
Coding c = (Coding) fixed;
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions , c.getSystem(), c.getCode(), c.getDisplay());
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions , c.getSystem(), c.getVersion(), 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(terminologyServiceOptions, c.getSystem(), c.getCode(), c.getDisplay());
|
||||
ValidationResult vr = context.validateCode(terminologyServiceOptions, c.getSystem(), c.getVersion(), c.getCode(), c.getDisplay());
|
||||
if (vr.getDisplay() != null)
|
||||
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
||||
}
|
||||
|
|
|
@ -726,16 +726,16 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
// --- validate code -------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String code, String display) {
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display) {
|
||||
assert options != null;
|
||||
Coding c = new Coding(system, code, display);
|
||||
Coding c = new Coding(system, version, code, display);
|
||||
return validateCode(options, c, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ValueSet vs) {
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display, ValueSet vs) {
|
||||
assert options != null;
|
||||
Coding c = new Coding(system, code, display);
|
||||
Coding c = new Coding(system, version, code, display);
|
||||
return validateCode(options, c, vs);
|
||||
}
|
||||
|
||||
|
@ -782,9 +782,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
for (CodingValidationRequest t : codes) {
|
||||
if (!t.hasResult()) {
|
||||
String codeKey = t.getCoding().hasVersion() ? t.getCoding().getSystem()+"|"+t.getCoding().getVersion() : t.getCoding().getSystem();
|
||||
if (!options.isUseServer()) {
|
||||
t.setResult(new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS));
|
||||
} else if (unsupportedCodeSystems.contains(t.getCoding().getSystem())) {
|
||||
} else if (unsupportedCodeSystems.contains(codeKey)) {
|
||||
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED));
|
||||
} else if (noTerminologyServer) {
|
||||
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE));
|
||||
|
@ -882,10 +883,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
|
||||
String codeKey = code.hasVersion() ? code.getSystem()+"|"+code.getVersion() : code.getSystem();
|
||||
if (!options.isUseServer()) {
|
||||
return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS);
|
||||
}
|
||||
if (unsupportedCodeSystems.contains(code.getSystem())) {
|
||||
if (unsupportedCodeSystems.contains(codeKey)) {
|
||||
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, code.getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
|
||||
}
|
||||
|
||||
|
@ -910,8 +912,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
} catch (Exception e) {
|
||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR);
|
||||
}
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
unsupportedCodeSystems.add(code.getSystem());
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED && !code.hasVersion()) {
|
||||
unsupportedCodeSystems.add(codeKey);
|
||||
} else if (txCache != null) { // we never cache unsuppoted code systems - we always keep trying (but only once per run)
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT);
|
||||
}
|
||||
|
@ -925,6 +927,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (options.getValueSetMode() != ValueSetMode.ALL_CHECKS) {
|
||||
pIn.addParameter("valueSetMode", options.getValueSetMode().toString());
|
||||
}
|
||||
if (options.versionFlexible()) {
|
||||
pIn.addParameter("default-to-latest-version", true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1118,6 +1123,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
txCache.removeCS(url);
|
||||
}
|
||||
|
||||
public void clearTS() {
|
||||
txCache.clear();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ConceptMap> findMapsForSource(String url) throws FHIRException {
|
||||
|
|
|
@ -544,6 +544,12 @@ public interface IWorkerContext {
|
|||
private TerminologyServiceErrorClass errorClass;
|
||||
private String txLink;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass="
|
||||
+ errorClass + ", txLink=" + txLink + "]";
|
||||
}
|
||||
|
||||
public ValidationResult(IssueSeverity severity, String message) {
|
||||
this.severity = severity;
|
||||
this.message = message;
|
||||
|
@ -583,6 +589,10 @@ public interface IWorkerContext {
|
|||
return definition == null ? null : definition.getCode();
|
||||
}
|
||||
|
||||
public String getDefinition() {
|
||||
return definition == null ? null : definition.getDefinition();
|
||||
}
|
||||
|
||||
public ConceptDefinitionComponent asConceptDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
@ -671,7 +681,7 @@ public interface IWorkerContext {
|
|||
* @param display - equals Coding.display (optional)
|
||||
* @return
|
||||
*/
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String code, String display);
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display);
|
||||
|
||||
/**
|
||||
* Validation of a code - consult the terminology infrstructure and/or service
|
||||
|
@ -688,7 +698,7 @@ public interface IWorkerContext {
|
|||
* @param vs the applicable valueset (optional)
|
||||
* @return
|
||||
*/
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ValueSet vs);
|
||||
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display, ValueSet vs);
|
||||
|
||||
/**
|
||||
* Validation of a code - consult the terminology infrstructure and/or service
|
||||
|
|
|
@ -124,6 +124,9 @@ public class TerminologyCache {
|
|||
load();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
caches.clear();
|
||||
}
|
||||
public CacheToken generateValidationToken(ValidationOptions options, Coding code, ValueSet vs) {
|
||||
CacheToken ct = new CacheToken();
|
||||
if (code.hasSystem())
|
||||
|
@ -337,11 +340,36 @@ public class TerminologyCache {
|
|||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.e.getError()).trim()+"\"\r\n}\r\n");
|
||||
} else {
|
||||
sw.write("v: {\r\n");
|
||||
sw.write(" \"display\" : \""+Utilities.escapeJson(ce.v.getDisplay()).trim()+"\",\r\n");
|
||||
sw.write(" \"code\" : \""+Utilities.escapeJson(ce.v.getCode()).trim()+"\",\r\n");
|
||||
sw.write(" \"system\" : \""+Utilities.escapeJson(ce.v.getSystem()).trim()+"\",\r\n");
|
||||
sw.write(" \"severity\" : "+(ce.v.getSeverity() == null ? "null" : "\""+ce.v.getSeverity().toCode().trim()+"\"")+",\r\n");
|
||||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.v.getMessage()).trim()+"\"\r\n}\r\n");
|
||||
boolean first = true;
|
||||
if (ce.v.getDisplay() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"display\" : \""+Utilities.escapeJson(ce.v.getDisplay()).trim()+"\"");
|
||||
}
|
||||
if (ce.v.getCode() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"code\" : \""+Utilities.escapeJson(ce.v.getCode()).trim()+"\"");
|
||||
}
|
||||
if (ce.v.getSystem() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"system\" : \""+Utilities.escapeJson(ce.v.getSystem()).trim()+"\"");
|
||||
}
|
||||
if (ce.v.getSeverity() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"severity\" : "+"\""+ce.v.getSeverity().toCode().trim()+"\""+"");
|
||||
}
|
||||
if (ce.v.getMessage() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.v.getMessage()).trim()+"\"");
|
||||
}
|
||||
if (ce.v.getErrorClass() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"class\" : \""+Utilities.escapeJson(ce.v.getErrorClass().toString())+"\"");
|
||||
}
|
||||
if (ce.v.getDefinition() != null) {
|
||||
if (first) first = false; else sw.write(",\r\n");
|
||||
sw.write(" \"definition\" : \""+Utilities.escapeJson(ce.v.getDefinition()).trim()+"\"");
|
||||
}
|
||||
sw.write("\r\n}\r\n");
|
||||
}
|
||||
sw.write(ENTRY_MARKER+"\r\n");
|
||||
}
|
||||
|
@ -386,11 +414,15 @@ public class TerminologyCache {
|
|||
else
|
||||
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN);
|
||||
} else {
|
||||
IssueSeverity severity = o.get("severity") instanceof JsonNull ? null : IssueSeverity.fromCode(o.get("severity").getAsString());
|
||||
String t = loadJS(o.get("severity"));
|
||||
IssueSeverity severity = t == null ? null : IssueSeverity.fromCode(t);
|
||||
String display = loadJS(o.get("display"));
|
||||
String code = loadJS(o.get("code"));
|
||||
String system = loadJS(o.get("system"));
|
||||
ce.v = new ValidationResult(severity, error, system, new ConceptDefinitionComponent().setDisplay(display).setCode(code));
|
||||
String definition = loadJS(o.get("definition"));
|
||||
t = loadJS(o.get("class"));
|
||||
TerminologyServiceErrorClass errorClass = t == null ? null : TerminologyServiceErrorClass.valueOf(t) ;
|
||||
ce.v = new ValidationResult(severity, error, system, new ConceptDefinitionComponent().setDisplay(display).setDefinition(definition).setCode(code)).setErrorClass(errorClass);
|
||||
}
|
||||
nc.map.put(String.valueOf(hashNWS(ce.request)), ce);
|
||||
nc.list.add(ce);
|
||||
|
|
|
@ -605,6 +605,12 @@ public class Coding extends DataType implements IBaseCoding, ICompositeType, ICo
|
|||
return res;
|
||||
}
|
||||
|
||||
public Coding(String theSystem, String theVersion, String theCode, String theDisplay) {
|
||||
setSystem(theSystem);
|
||||
setVersion(theVersion);
|
||||
setCode(theCode);
|
||||
setDisplay(theDisplay);
|
||||
}
|
||||
// end addition
|
||||
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
tr = tbl.tr();
|
||||
XhtmlNode td = tr.td();
|
||||
td.addText(ccl.getCode());
|
||||
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
|
||||
display = getDisplayForConcept(systemFromCanonical(grp.getSource()), versionFromCanonical(grp.getSource()), ccl.getCode());
|
||||
if (display != null && !isSameCodeAndDisplay(ccl.getCode(), display))
|
||||
td.tx(" ("+display+")");
|
||||
TargetElementComponent ccm = ccl.getTarget().get(0);
|
||||
|
@ -152,7 +152,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
}
|
||||
td = tr.td();
|
||||
td.addText(ccm.getCode());
|
||||
display = getDisplayForConcept(grp.getTarget(), ccm.getCode());
|
||||
display = getDisplayForConcept(systemFromCanonical(grp.getTarget()), versionFromCanonical(grp.getTarget()), ccm.getCode());
|
||||
if (display != null && !isSameCodeAndDisplay(ccm.getCode(), display))
|
||||
td.tx(" ("+display+")");
|
||||
if (comment)
|
||||
|
@ -217,7 +217,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
td.addText(ccl.getCode());
|
||||
else
|
||||
td.addText(grp.getSource()+" / "+ccl.getCode());
|
||||
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
|
||||
display = getDisplayForConcept(systemFromCanonical(grp.getSource()), versionFromCanonical(grp.getSource()), ccl.getCode());
|
||||
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
|
||||
tr.td().colspan("4").style("background-color: #efefef").tx("(not mapped)");
|
||||
|
||||
|
@ -238,7 +238,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
td.addText(ccl.getCode());
|
||||
else
|
||||
td.addText(grp.getSource()+" / "+ccl.getCode());
|
||||
display = getDisplayForConcept(grp.getSource(), ccl.getCode());
|
||||
display = getDisplayForConcept(systemFromCanonical(grp.getSource()), versionFromCanonical(grp.getSource()), ccl.getCode());
|
||||
td = tr.td();
|
||||
if (!first)
|
||||
td.style("border-left-width: 0px; border-top-style: none");
|
||||
|
@ -283,7 +283,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
td.addText(ccm.getCode());
|
||||
else
|
||||
td.addText(grp.getTarget()+" / "+ccm.getCode());
|
||||
display = getDisplayForConcept(grp.getTarget(), ccm.getCode());
|
||||
display = getDisplayForConcept(systemFromCanonical(grp.getTarget()), versionFromCanonical(grp.getTarget()), ccm.getCode());
|
||||
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
|
||||
|
||||
for (String s : targets.keySet()) {
|
||||
|
@ -408,11 +408,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
private String getDisplay(List<OtherElementComponent> list, String s) {
|
||||
for (OtherElementComponent c : list) {
|
||||
if (s.equals(c.getProperty()))
|
||||
return getDisplayForConcept(c.getSystem(), c.getValue());
|
||||
return getDisplayForConcept(systemFromCanonical(c.getSystem()), versionFromCanonical(c.getSystem()), c.getValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -191,8 +191,8 @@ public class DataRenderer extends Renderer {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
private String lookupCode(String system, String code) {
|
||||
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), system, code, null);
|
||||
private String lookupCode(String system, String version, String code) {
|
||||
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().setVersionFlexible(true), system, version, code, null);
|
||||
|
||||
if (t != null && t.getDisplay() != null)
|
||||
return t.getDisplay();
|
||||
|
@ -484,7 +484,7 @@ public class DataRenderer extends Renderer {
|
|||
if (c.hasDisplayElement())
|
||||
return c.getDisplay();
|
||||
if (Utilities.noString(s))
|
||||
s = lookupCode(c.getSystem(), c.getCode());
|
||||
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||
if (Utilities.noString(s))
|
||||
s = c.getCode();
|
||||
return s;
|
||||
|
@ -507,7 +507,7 @@ public class DataRenderer extends Renderer {
|
|||
if (c.hasDisplayElement())
|
||||
s = c.getDisplay();
|
||||
if (Utilities.noString(s))
|
||||
s = lookupCode(c.getSystem(), c.getCode());
|
||||
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||
|
||||
|
||||
String sn = describeSystem(c.getSystem());
|
||||
|
@ -539,13 +539,13 @@ public class DataRenderer extends Renderer {
|
|||
if (c.hasDisplayElement())
|
||||
s = c.getDisplay();
|
||||
if (Utilities.noString(s))
|
||||
s = lookupCode(c.getSystem(), c.getCode());
|
||||
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||
|
||||
if (Utilities.noString(s))
|
||||
s = c.getCode();
|
||||
|
||||
if (showCodeDetails) {
|
||||
x.addText(s+" (Details: "+TerminologyRenderer.describeSystem(c.getSystem())+" code "+c.getCode()+" = '"+lookupCode(c.getSystem(), c.getCode())+"', stated as '"+c.getDisplay()+"')");
|
||||
x.addText(s+" (Details: "+TerminologyRenderer.describeSystem(c.getSystem())+" code "+c.getCode()+" = '"+lookupCode(c.getSystem(), c.getVersion(), c.getCode())+"', stated as '"+c.getDisplay()+"')");
|
||||
} else
|
||||
x.span(null, "{"+c.getSystem()+" "+c.getCode()+"}").addText(s);
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ public class DataRenderer extends Renderer {
|
|||
// still? ok, let's try looking it up
|
||||
for (Coding c : cc.getCoding()) {
|
||||
if (c.hasCode() && c.hasSystem()) {
|
||||
s = lookupCode(c.getSystem(), c.getCode());
|
||||
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||
if (!Utilities.noString(s))
|
||||
break;
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ public class DataRenderer extends Renderer {
|
|||
// still? ok, let's try looking it up
|
||||
for (Coding c : cc.getCoding()) {
|
||||
if (c.hasCodeElement() && c.hasSystemElement()) {
|
||||
s = lookupCode(c.getSystem(), c.getCode());
|
||||
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||
if (!Utilities.noString(s))
|
||||
break;
|
||||
}
|
||||
|
@ -636,7 +636,7 @@ public class DataRenderer extends Renderer {
|
|||
first = false;
|
||||
} else
|
||||
sp.tx("; ");
|
||||
sp.tx("{"+TerminologyRenderer.describeSystem(c.getSystem())+" code '"+c.getCode()+"' = '"+lookupCode(c.getSystem(), c.getCode())+(c.hasDisplay() ? "', given as '"+c.getDisplay()+"'}" : ""));
|
||||
sp.tx("{"+TerminologyRenderer.describeSystem(c.getSystem())+" code '"+c.getCode()+"' = '"+lookupCode(c.getSystem(), c.getVersion(), c.getCode())+(c.hasDisplay() ? "', given as '"+c.getDisplay()+"'}" : ""));
|
||||
}
|
||||
sp.tx(")");
|
||||
} else {
|
||||
|
@ -661,7 +661,7 @@ public class DataRenderer extends Renderer {
|
|||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay())
|
||||
s = ii.getType().getCoding().get(0).getDisplay()+": "+s;
|
||||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode())
|
||||
s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getCode())+": "+s;
|
||||
s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getVersion(), ii.getType().getCoding().get(0).getCode())+": "+s;
|
||||
} else {
|
||||
s = "id: "+s;
|
||||
}
|
||||
|
@ -838,7 +838,7 @@ public class DataRenderer extends Renderer {
|
|||
|
||||
s.append("(system = '").append(TerminologyRenderer.describeSystem(q.getSystem()))
|
||||
.append("' code ").append(q.getCode())
|
||||
.append(" = '").append(lookupCode(q.getSystem(), q.getCode())).append("')");
|
||||
.append(" = '").append(lookupCode(q.getSystem(), null, q.getCode())).append("')");
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
@ -858,7 +858,7 @@ public class DataRenderer extends Renderer {
|
|||
else if (q.hasCode())
|
||||
x.tx(" "+q.getCode());
|
||||
if (showCodeDetails && q.hasCode()) {
|
||||
x.span("background: LightGoldenRodYellow", null).tx(" (Details: "+TerminologyRenderer.describeSystem(q.getSystem())+" code "+q.getCode()+" = '"+lookupCode(q.getSystem(), q.getCode())+"')");
|
||||
x.span("background: LightGoldenRodYellow", null).tx(" (Details: "+TerminologyRenderer.describeSystem(q.getSystem())+" code "+q.getCode()+" = '"+lookupCode(q.getSystem(), null, q.getCode())+"')");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1160,4 +1160,25 @@ public class DataRenderer extends Renderer {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
protected String versionFromCanonical(String system) {
|
||||
if (system == null) {
|
||||
return null;
|
||||
} else if (system.contains("|")) {
|
||||
return system.substring(0, system.indexOf("|"));
|
||||
} else {
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
protected String systemFromCanonical(String system) {
|
||||
if (system == null) {
|
||||
return null;
|
||||
} else if (system.contains("|")) {
|
||||
return system.substring(system.indexOf("|")+1);
|
||||
} else {
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -309,10 +309,10 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
|
|||
|
||||
|
||||
|
||||
protected String getDisplayForConcept(String system, String value) {
|
||||
protected String getDisplayForConcept(String system, String version, String value) {
|
||||
if (value == null || system == null)
|
||||
return null;
|
||||
ValidationResult cl = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), system, value, null);
|
||||
ValidationResult cl = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().setVersionFlexible(true), system, version, value, null);
|
||||
return cl == null ? null : cl.getDisplay();
|
||||
}
|
||||
|
||||
|
|
|
@ -896,7 +896,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
li.ah(href).addText(f.getValue());
|
||||
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
||||
li.addText(f.getValue());
|
||||
ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), f.getValue(), null);
|
||||
ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), inc.getVersion(), f.getValue(), null);
|
||||
if (vr.isOk()) {
|
||||
li.tx(" ("+vr.getDisplay()+")");
|
||||
}
|
||||
|
|
|
@ -25,9 +25,11 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
|
|||
import org.hl7.fhir.exceptions.PathEngineException;
|
||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Constants;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.DateType;
|
||||
|
@ -54,6 +56,7 @@ import org.hl7.fhir.r5.model.TypeConvertor;
|
|||
import org.hl7.fhir.r5.model.TypeDetails;
|
||||
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.DataRenderer;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
@ -2329,7 +2332,8 @@ public class FHIRPathEngine {
|
|||
|
||||
private List<Base> opMemberOf(ExecutionContext context, List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||
boolean ans = false;
|
||||
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, right.get(0).primitiveValue()) : worker.fetchResource(ValueSet.class, right.get(0).primitiveValue());
|
||||
String url = right.get(0).primitiveValue();
|
||||
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, url) : worker.fetchResource(ValueSet.class, url);
|
||||
if (vs != null) {
|
||||
for (Base l : left) {
|
||||
if (Utilities.existsInList(l.fhirType(), "code", "string", "uri")) {
|
||||
|
@ -2341,7 +2345,10 @@ public class FHIRPathEngine {
|
|||
ans = true;
|
||||
}
|
||||
} else if (l.fhirType().equals("CodeableConcept")) {
|
||||
if (worker.validateCode(terminologyServiceOptions, TypeConvertor.castToCodeableConcept(l), vs).isOk()) {
|
||||
CodeableConcept cc = TypeConvertor.castToCodeableConcept(l);
|
||||
ValidationResult vr = worker.validateCode(terminologyServiceOptions, cc, vs);
|
||||
// System.out.println("~~~ "+DataRenderer.display(worker, cc)+ " memberOf "+url+": "+vr.toString());
|
||||
if (vr.isOk()) {
|
||||
ans = true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -322,16 +322,9 @@ public class NPMPackageGenerator {
|
|||
|
||||
public void addFile(Category cat, String name, byte[] content) throws IOException {
|
||||
String path = cat.getDirectory()+name;
|
||||
if (!path.startsWith("package/")) {
|
||||
path = "package/" +path;
|
||||
}
|
||||
if (path.length() > 100) {
|
||||
name = name.substring(0, name.indexOf("-"))+"-"+UUID.randomUUID().toString();
|
||||
path = cat.getDirectory()+name;
|
||||
if (!path.startsWith("package/")) {
|
||||
path = "package/" +path;
|
||||
}
|
||||
|
||||
path = cat.getDirectory()+name;
|
||||
}
|
||||
|
||||
if (created.contains(path)) {
|
||||
|
|
|
@ -1752,6 +1752,7 @@ public class StructureMapUtilities {
|
|||
// if we can get this as a valueSet, we will
|
||||
String system = null;
|
||||
String display = null;
|
||||
String version = null;
|
||||
ValueSet vs = Utilities.noString(uri) ? null : worker.fetchResourceWithException(ValueSet.class, uri);
|
||||
if (vs != null) {
|
||||
ValueSetExpansionOutcome vse = worker.expandVS(vs, true, false);
|
||||
|
@ -1763,20 +1764,23 @@ public class StructureMapUtilities {
|
|||
b.append(t.getCode());
|
||||
if (code.equals(t.getCode()) && t.hasSystem()) {
|
||||
system = t.getSystem();
|
||||
version = t.getVersion();
|
||||
display = t.getDisplay();
|
||||
break;
|
||||
}
|
||||
if (code.equalsIgnoreCase(t.getDisplay()) && t.hasSystem()) {
|
||||
system = t.getSystem();
|
||||
version = t.getVersion();
|
||||
display = t.getDisplay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (system == null)
|
||||
throw new FHIRException("The code '" + code + "' is not in the value set '" + uri + "' (valid codes: " + b.toString() + "; also checked displays)");
|
||||
} else
|
||||
} else {
|
||||
system = uri;
|
||||
ValidationResult vr = worker.validateCode(terminologyServiceOptions, system, code, null);
|
||||
}
|
||||
ValidationResult vr = worker.validateCode(terminologyServiceOptions.setVersionFlexible(true), system, version, code, null);
|
||||
if (vr != null && vr.getDisplay() != null)
|
||||
display = vr.getDisplay();
|
||||
return new Coding().setSystem(system).setCode(code).setDisplay(display);
|
||||
|
|
|
@ -105,8 +105,10 @@ public class I18nConstants {
|
|||
public static final String ERROR_READING__FROM_PACKAGE__ = "Error_reading__from_package__";
|
||||
public static final String ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES = "Error_validating_code_running_without_terminology_services";
|
||||
public static final String ERROR_WRITING_NUMBER__TO_JSON = "error_writing_number__to_JSON";
|
||||
public static final String EXTENSION_EXT_CONTEXT_WRONG = "Extension_EXT_Context_Wrong";
|
||||
public static final String EXTENSION_EXT_CONTEXT_WRONG_XVER = "EXTENSION_EXT_CONTEXT_WRONG_XVER";
|
||||
public static final String EXTENSION_EXTP_CONTEXT_WRONG = "Extension_EXTP_Context_Wrong";
|
||||
public static final String EXTENSION_EXTP_CONTEXT_WRONG_XVER = "EXTENSION_EXTP_CONTEXT_WRONG_XVER";
|
||||
public static final String EXTENSION_EXTM_CONTEXT_WRONG = "Extension_EXTM_Context_Wrong";
|
||||
public static final String EXTENSION_EXTM_CONTEXT_WRONG_XVER = "EXTENSION_EXTM_CONTEXT_WRONG_XVER";
|
||||
public static final String EXTENSION_EXT_COUNT_MISMATCH = "Extension_EXT_Count_Mismatch";
|
||||
public static final String EXTENSION_EXT_COUNT_NOTFOUND = "Extension_EXT_Count_NotFound";
|
||||
public static final String EXTENSION_EXT_FIXED_BANNED = "Extension_EXT_Fixed_Banned";
|
||||
|
|
|
@ -12,6 +12,7 @@ public class ValidationOptions {
|
|||
private boolean guessSystem = false;
|
||||
private ValueSetMode valueSetMode = ValueSetMode.ALL_CHECKS;
|
||||
private boolean vsAsUrl;
|
||||
private boolean versionFlexible = true;
|
||||
|
||||
public ValidationOptions() {
|
||||
super();
|
||||
|
@ -45,6 +46,7 @@ public class ValidationOptions {
|
|||
n.useClient = useClient;
|
||||
n.guessSystem = guessSystem;
|
||||
n.vsAsUrl = vsAsUrl;
|
||||
n.versionFlexible = versionFlexible;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,8 @@ public class ValidationOptions {
|
|||
|
||||
|
||||
public String toJson() {
|
||||
return "\"lang\":\""+language+"\", \"useServer\":\""+Boolean.toString(useServer)+"\", \"useClient\":\""+Boolean.toString(useClient)+"\", \"guessSystem\":\""+Boolean.toString(guessSystem)+"\", \"valueSetMode\":\""+valueSetMode.toString()+"\"";
|
||||
return "\"lang\":\""+language+"\", \"useServer\":\""+Boolean.toString(useServer)+"\", \"useClient\":\""+Boolean.toString(useClient)+"\", "+
|
||||
"\"guessSystem\":\""+Boolean.toString(guessSystem)+"\", \"valueSetMode\":\""+valueSetMode.toString()+"\", \"versionFlexible\":\""+Boolean.toString(versionFlexible)+"\"";
|
||||
}
|
||||
|
||||
public static ValidationOptions defaults() {
|
||||
|
@ -107,5 +110,15 @@ public class ValidationOptions {
|
|||
return vsAsUrl;
|
||||
}
|
||||
|
||||
public boolean versionFlexible() {
|
||||
return versionFlexible;
|
||||
}
|
||||
|
||||
public ValidationOptions setVersionFlexible(boolean value) {
|
||||
ValidationOptions n = this.copy();
|
||||
n.versionFlexible = value;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -26,7 +26,8 @@ CodeSystem_CS_VS_IncludeDetails = CodeSystem {0} has an ''all system'' value set
|
|||
CodeSystem_CS_VS_Invalid = CodeSystem {0} has an ''all system'' value set of {1}, but doesn''t have a single include
|
||||
CODESYSTEM_CS_VS_EXP_MISMATCH = CodeSystem {0} has an ''all system'' value set of {1}, but it is an expansion with the wrong number of concepts (found {2}, expected {3})
|
||||
CodeSystem_CS_VS_WrongSystem = CodeSystem {0} has an ''all system'' value set of {1}, but doesn''t have a matching system ({2})
|
||||
Extension_EXT_Context_Wrong = The extension {0} is not allowed to be used at this point (allowed = {1}; this element is [{2})
|
||||
Extension_EXTP_Context_Wrong = The extension {0} is not allowed to be used at this point (allowed = {1}; this element is [{2})
|
||||
Extension_EXTM_Context_Wrong = The modifier extension {0} is not allowed to be used at this point (allowed = {1}; this element is [{2})
|
||||
Extension_EXT_Count_Mismatch = Extensions count mismatch: expected {0} but found {1}
|
||||
Extension_EXT_Count_NotFound = Extension count mismatch: unable to find extension: {0}
|
||||
Extension_EXT_Fixed_Banned = No extensions allowed, as the specified fixed value doesn''t contain any extensions
|
||||
|
@ -505,7 +506,8 @@ TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS = Found {0} decimal places which exceeds t
|
|||
Validation_VAL_Profile_WrongType = Specified profile type was ''{0}'' in profile ''{2}'', but found type ''{1}''
|
||||
Validation_VAL_Profile_WrongType2 = Type mismatch processing profile {0} at path {1}: The element type is {4}, but the profile {3} is for a different type {2}
|
||||
VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT = Illegal constraint in profile {0} at path {1} - cannot constrain to type {2} from base types {3}
|
||||
EXTENSION_EXT_CONTEXT_WRONG_XVER = The extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions)
|
||||
EXTENSION_EXTP_CONTEXT_WRONG_XVER = The extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions)
|
||||
EXTENSION_EXTM_CONTEXT_WRONG_XVER = The modifier extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions)
|
||||
SECURITY_STRING_CONTENT_ERROR = The string value contains text that looks like embedded HTML tags, which are not allowed for security reasons in this context
|
||||
SECURITY_STRING_CONTENT_WARNING = The string value contains text that looks like embedded HTML tags. If this content is rendered to HTML without appropriate post-processing, it may be a security risk
|
||||
ALL_OK = All OK
|
||||
|
|
|
@ -1007,4 +1007,24 @@ public class BaseValidator {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String versionFromCanonical(String system) {
|
||||
if (system == null) {
|
||||
return null;
|
||||
} else if (system.contains("|")) {
|
||||
return system.substring(0, system.indexOf("|"));
|
||||
} else {
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
protected String systemFromCanonical(String system) {
|
||||
if (system == null) {
|
||||
return null;
|
||||
} else if (system.contains("|")) {
|
||||
return system.substring(system.indexOf("|")+1);
|
||||
} else {
|
||||
return system;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -396,6 +396,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private List<BundleValidationRule> bundleValidationRules = new ArrayList<>();
|
||||
private boolean validateValueSetCodesOnTxServer = true;
|
||||
private QuestionnaireMode questionnaireMode;
|
||||
private ValidationOptions baseOptions = new ValidationOptions();
|
||||
|
||||
public InstanceValidator(IWorkerContext theContext, IEvaluationContext hostServices, XVerExtensionManager xverManager) {
|
||||
super(theContext, xverManager);
|
||||
|
@ -836,13 +837,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, NodeStack stack) throws TerminologyServiceException {
|
||||
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String version, String display, boolean checkDisplay, NodeStack stack) throws TerminologyServiceException {
|
||||
long t = System.nanoTime();
|
||||
boolean ss = context.supportsSystem(system);
|
||||
timeTracker.tx(t, "ss "+system);
|
||||
if (ss) {
|
||||
t = System.nanoTime();
|
||||
ValidationResult s = checkCodeOnServer(stack, code, system, display, checkDisplay);
|
||||
ValidationResult s = checkCodeOnServer(stack, code, system, version, display, checkDisplay);
|
||||
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
|
||||
if (s == null)
|
||||
return true;
|
||||
|
@ -1251,8 +1252,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
for (Coding nextCoding : cc.getCoding()) {
|
||||
String nextCode = nextCoding.getCode();
|
||||
String nextSystem = nextCoding.getSystem();
|
||||
String nextVersion = nextCoding.getVersion();
|
||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
ValidationResult vr = checkCodeOnServer(stack, nextCode, nextSystem, null, false);
|
||||
ValidationResult vr = checkCodeOnServer(stack, nextCode, nextSystem, nextVersion, null, false);
|
||||
if (!vr.isOk()) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_NOTVALID, nextCode, nextSystem);
|
||||
}
|
||||
|
@ -1286,12 +1288,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
String code = c.getCode();
|
||||
String system = c.getSystem();
|
||||
String display = c.getDisplay();
|
||||
String version = c.getVersion();
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
|
||||
if (system != null && code != null && !noTerminologyChecks) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
|
||||
try {
|
||||
if (checkCode(errors, element, path, code, system, display, checkDisplay, stack))
|
||||
if (checkCode(errors, element, path, code, system, version, display, checkDisplay, stack))
|
||||
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
|
||||
|
@ -1473,7 +1476,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(maxVSUrl))) {
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, value, new ValidationOptions(stack.getWorkingLang()));
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, value, baseOptions.setLanguage(stack.getWorkingLang()));
|
||||
timeTracker.tx(t, "vc "+value);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1506,19 +1509,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
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 version = element.getNamedChildValue("version");
|
||||
String display = element.getNamedChildValue("display");
|
||||
checkCodedElement(errors, path, element, profile, theElementCntext, inCodeableConcept, checkDisplay, stack, code, system, display);
|
||||
checkCodedElement(errors, path, element, profile, theElementCntext, inCodeableConcept, checkDisplay, stack, code, system, version, display);
|
||||
}
|
||||
|
||||
private void checkCodedElement(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay, NodeStack stack,
|
||||
String theCode, String theSystem, String theDisplay) {
|
||||
String theCode, String theSystem, String theVersion, String theDisplay) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, Utilities.noString(theCode) || !Utilities.noString(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_NO_CODE);
|
||||
|
||||
if (theSystem != null && theCode != null && !noTerminologyChecks) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, theSystem);
|
||||
try {
|
||||
if (checkCode(errors, element, path, theCode, theSystem, theDisplay, checkDisplay, stack))
|
||||
if (checkCode(errors, element, path, theCode, theSystem, theVersion, theDisplay, checkDisplay, stack))
|
||||
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
|
||||
|
@ -1633,7 +1637,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
// two questions
|
||||
// 1. can this extension be used here?
|
||||
checkExtensionContext(errors, resource, container, ex, containerStack, hostContext);
|
||||
checkExtensionContext(errors, resource, container, ex, containerStack, hostContext, isModifier);
|
||||
|
||||
if (isModifier)
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", ex.getSnapshot().getElement().get(0).getIsModifier(), I18nConstants.EXTENSION_EXT_MODIFIER_Y, url);
|
||||
|
@ -1697,7 +1701,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return res;
|
||||
}
|
||||
|
||||
private boolean checkExtensionContext(List<ValidationMessage> errors, Element resource, Element container, StructureDefinition definition, NodeStack stack, ValidatorHostContext hostContext) {
|
||||
private boolean checkExtensionContext(List<ValidationMessage> errors, Element resource, Element container, StructureDefinition definition, NodeStack stack, ValidatorHostContext hostContext, boolean modifier) {
|
||||
String extUrl = definition.getUrl();
|
||||
boolean ok = false;
|
||||
CommaSeparatedStringBuilder contexts = new CommaSeparatedStringBuilder();
|
||||
|
@ -1774,9 +1778,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
if (!ok) {
|
||||
if (definition.hasUserData(XVerExtensionManager.XVER_EXT_MARKER)) {
|
||||
warning(errors, IssueType.STRUCTURE, container.line(), container.col(), stack.getLiteralPath(), false, I18nConstants.EXTENSION_EXT_CONTEXT_WRONG_XVER, extUrl, contexts.toString(), plist.toString());
|
||||
warning(errors, IssueType.STRUCTURE, container.line(), container.col(), stack.getLiteralPath(), false,
|
||||
modifier ? I18nConstants.EXTENSION_EXTM_CONTEXT_WRONG_XVER : I18nConstants.EXTENSION_EXTP_CONTEXT_WRONG_XVER, extUrl, contexts.toString(), plist.toString());
|
||||
} else {
|
||||
rule(errors, IssueType.STRUCTURE, container.line(), container.col(), stack.getLiteralPath(), false, I18nConstants.EXTENSION_EXT_CONTEXT_WRONG, extUrl, contexts.toString(), plist.toString());
|
||||
rule(errors, IssueType.STRUCTURE, container.line(), container.col(), stack.getLiteralPath(), false,
|
||||
modifier ? I18nConstants.EXTENSION_EXTP_CONTEXT_WRONG : I18nConstants.EXTENSION_EXTM_CONTEXT_WRONG, extUrl, contexts.toString(), plist.toString());
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
|
@ -2484,7 +2490,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
long t = System.nanoTime();
|
||||
ValidationResult vr = null;
|
||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
ValidationOptions options = new ValidationOptions(stack.getWorkingLang()).guessSystem();
|
||||
ValidationOptions options = baseOptions.setLanguage(stack.getWorkingLang()).guessSystem();
|
||||
vr = checkCodeOnServer(stack, vs, value, options);
|
||||
}
|
||||
timeTracker.tx(t, "vc "+value+"");
|
||||
|
@ -2543,7 +2549,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
if (system != null || code != null ) {
|
||||
checkCodedElement(theErrors, thePath, element, theProfile, definition, false, false, theStack, code, system, unit);
|
||||
checkCodedElement(theErrors, thePath, element, theProfile, definition, false, false, theStack, code, system, null, unit);
|
||||
}
|
||||
|
||||
if (code != null && "http://unitsofmeasure.org".equals(system)) {
|
||||
|
@ -4188,7 +4194,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else if (element.getType().equals("CapabilityStatement")) {
|
||||
validateCapabilityStatement(errors, element, stack);
|
||||
} else if (element.getType().equals("CodeSystem")) {
|
||||
new CodeSystemValidator(context, timeTracker, xverManager).validateCodeSystem(errors, element, stack, new ValidationOptions(stack.getWorkingLang()));
|
||||
new CodeSystemValidator(context, timeTracker, xverManager).validateCodeSystem(errors, element, stack, baseOptions.setLanguage(stack.getWorkingLang()));
|
||||
} else if (element.getType().equals("SearchParameter")) {
|
||||
new SearchParameterValidator(context, timeTracker, fpe, xverManager).validateSearchParameter(errors, element, stack);
|
||||
} else if (element.getType().equals("StructureDefinition")) {
|
||||
|
@ -4405,7 +4411,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
if (definition.getPath().equals("StructureDefinition.snapshot")) {
|
||||
// work around a known issue in the spec, that idsa are duplicated in snapshot and differential
|
||||
// work around a known issue in the spec, that ids are duplicated in snapshot and differential
|
||||
stack.resetIds();
|
||||
}
|
||||
|
||||
|
@ -4993,6 +4999,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else {
|
||||
if (nameMatches(ei.getName(), tail(ed.getPath())))
|
||||
try {
|
||||
// System.out.println("match slices for "+stack.getLiteralPath()+": "+slicer.getId()+" = "+slicingSummary(slicer.getSlicing()));
|
||||
match = sliceMatches(hostContext, ei.getElement(), ei.getPath(), slicer, ed, profile, errors, sliceInfo, stack, profile);
|
||||
if (match) {
|
||||
ei.slice = slicer;
|
||||
|
@ -5026,6 +5033,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return unsupportedSlicing;
|
||||
}
|
||||
|
||||
private String slicingSummary(ElementDefinitionSlicingComponent slicing) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append('[');
|
||||
boolean first = true;
|
||||
for (ElementDefinitionSlicingDiscriminatorComponent t : slicing.getDiscriminator()) {
|
||||
if (first) first = false; else b.append(",");
|
||||
b.append(t.getType().toCode());
|
||||
b.append(":");
|
||||
b.append(t.getPath());
|
||||
}
|
||||
b.append(']');
|
||||
b.append(slicing.getOrdered() ? ";ordered" : "");
|
||||
b.append(slicing.getRules().toString());
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private ElementDefinition getElementByTail(StructureDefinition p, String tail) throws DefinitionException {
|
||||
if (tail == null)
|
||||
return p.getSnapshot().getElement().get(0);
|
||||
|
@ -5451,23 +5474,23 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
// no delay on this one?
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String display, boolean checkDisplay) {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()), system, code, checkDisplay ? display : null);
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String version, String display, boolean checkDisplay) {
|
||||
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()), system, version, code, checkDisplay ? display : null);
|
||||
}
|
||||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, Coding c, boolean checkMembership) {
|
||||
if (checkMembership) {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).checkValueSetOnly(), c, valueset);
|
||||
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()).checkValueSetOnly(), c, valueset);
|
||||
} else {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).noCheckValueSetMembership(), c, valueset);
|
||||
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()).noCheckValueSetMembership(), c, valueset);
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc, boolean vsOnly) {
|
||||
if (vsOnly) {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).checkValueSetOnly(), cc, valueset);
|
||||
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()).checkValueSetOnly(), cc, valueset);
|
||||
} else {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()), cc, valueset);
|
||||
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()), cc, valueset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5534,4 +5557,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
this.wantCheckSnapshotUnchanged = wantCheckSnapshotUnchanged;
|
||||
}
|
||||
|
||||
public ValidationOptions getBaseOptions() {
|
||||
return baseOptions;
|
||||
}
|
||||
|
||||
public void setBaseOptions(ValidationOptions baseOptions) {
|
||||
this.baseOptions = baseOptions;
|
||||
}
|
||||
|
||||
}
|
|
@ -77,7 +77,7 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
private void validateSupplementConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String supp, ValidationOptions options) {
|
||||
String code = concept.getChildValue("code");
|
||||
if (!Utilities.noString(code)) {
|
||||
org.hl7.fhir.r5.context.IWorkerContext.ValidationResult res = context.validateCode(options, supp, code, null);
|
||||
org.hl7.fhir.r5.context.IWorkerContext.ValidationResult res = context.validateCode(options, systemFromCanonical(supp), versionFromCanonical(supp), code, null);
|
||||
rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code);
|
||||
}
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
val.setWantCheckSnapshotUnchanged(true);
|
||||
val.getContext().setClientRetryCount(4);
|
||||
val.setDebug(false);
|
||||
|
||||
if (content.has("fetcher") && "standalone".equals(JSONUtil.str(content, "fetcher"))) {
|
||||
val.setFetcher(vCurr);
|
||||
vCurr.setFetcher(new StandAloneValidatorFetcher(vCurr.getPcm(), vCurr.getContext(), vCurr));
|
||||
|
@ -188,6 +189,11 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
val.setValidationLanguage(content.get("language").getAsString());
|
||||
else
|
||||
val.setValidationLanguage(null);
|
||||
if (content.has("default-version")) {
|
||||
val.setBaseOptions(val.getBaseOptions().setVersionFlexible(content.get("default-version").getAsBoolean()));
|
||||
} else {
|
||||
val.setBaseOptions(val.getBaseOptions().setVersionFlexible(false));
|
||||
}
|
||||
if (content.has("packages")) {
|
||||
for (JsonElement e : content.getAsJsonArray("packages")) {
|
||||
String n = e.getAsString();
|
||||
|
|
Loading…
Reference in New Issue