Merge pull request #624 from hapifhir/gg-202110-tx-version
fix terminology version management and caching + better error message…
This commit is contained in:
commit
2e075f674e
|
@ -4887,13 +4887,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private Piece describeCoded(HierarchicalTableGenerator gen, DataType fixed) {
|
private Piece describeCoded(HierarchicalTableGenerator gen, DataType fixed) {
|
||||||
if (fixed instanceof Coding) {
|
if (fixed instanceof Coding) {
|
||||||
Coding c = (Coding) fixed;
|
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)
|
if (vr.getDisplay() != null)
|
||||||
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
||||||
} else if (fixed instanceof CodeableConcept) {
|
} else if (fixed instanceof CodeableConcept) {
|
||||||
CodeableConcept cc = (CodeableConcept) fixed;
|
CodeableConcept cc = (CodeableConcept) fixed;
|
||||||
for (Coding c : cc.getCoding()) {
|
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)
|
if (vr.getDisplay() != null)
|
||||||
return gen.new Piece(null, " ("+vr.getDisplay()+")", null).addStyle("color: darkgreen");
|
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 -------------------------------------------------------------------------------
|
// --- validate code -------------------------------------------------------------------------------
|
||||||
|
|
||||||
@Override
|
@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;
|
assert options != null;
|
||||||
Coding c = new Coding(system, code, display);
|
Coding c = new Coding(system, version, code, display);
|
||||||
return validateCode(options, c, null);
|
return validateCode(options, c, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
assert options != null;
|
||||||
Coding c = new Coding(system, code, display);
|
Coding c = new Coding(system, version, code, display);
|
||||||
return validateCode(options, c, vs);
|
return validateCode(options, c, vs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,9 +782,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
|
|
||||||
for (CodingValidationRequest t : codes) {
|
for (CodingValidationRequest t : codes) {
|
||||||
if (!t.hasResult()) {
|
if (!t.hasResult()) {
|
||||||
|
String codeKey = t.getCoding().hasVersion() ? t.getCoding().getSystem()+"|"+t.getCoding().getVersion() : t.getCoding().getSystem();
|
||||||
if (!options.isUseServer()) {
|
if (!options.isUseServer()) {
|
||||||
t.setResult(new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS));
|
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));
|
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED));
|
||||||
} else if (noTerminologyServer) {
|
} else if (noTerminologyServer) {
|
||||||
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE));
|
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()) {
|
if (!options.isUseServer()) {
|
||||||
return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS);
|
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);
|
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) {
|
} 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);
|
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) {
|
if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED && !code.hasVersion()) {
|
||||||
unsupportedCodeSystems.add(code.getSystem());
|
unsupportedCodeSystems.add(codeKey);
|
||||||
} else if (txCache != null) { // we never cache unsuppoted code systems - we always keep trying (but only once per run)
|
} 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);
|
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT);
|
||||||
}
|
}
|
||||||
|
@ -925,6 +927,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
if (options.getValueSetMode() != ValueSetMode.ALL_CHECKS) {
|
if (options.getValueSetMode() != ValueSetMode.ALL_CHECKS) {
|
||||||
pIn.addParameter("valueSetMode", options.getValueSetMode().toString());
|
pIn.addParameter("valueSetMode", options.getValueSetMode().toString());
|
||||||
}
|
}
|
||||||
|
if (options.versionFlexible()) {
|
||||||
|
pIn.addParameter("default-to-latest-version", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1088,6 +1093,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
|
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
|
||||||
} else if (it == IssueType.NOTSUPPORTED) {
|
} else if (it == IssueType.NOTSUPPORTED) {
|
||||||
err = TerminologyServiceErrorClass.VALUESET_UNSUPPORTED;
|
err = TerminologyServiceErrorClass.VALUESET_UNSUPPORTED;
|
||||||
|
} else {
|
||||||
|
err = null;
|
||||||
}
|
}
|
||||||
} catch (FHIRException e) {
|
} catch (FHIRException e) {
|
||||||
}
|
}
|
||||||
|
@ -1118,6 +1125,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
txCache.removeCS(url);
|
txCache.removeCS(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearTS() {
|
||||||
|
txCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ConceptMap> findMapsForSource(String url) throws FHIRException {
|
public List<ConceptMap> findMapsForSource(String url) throws FHIRException {
|
||||||
|
|
|
@ -544,6 +544,12 @@ public interface IWorkerContext {
|
||||||
private TerminologyServiceErrorClass errorClass;
|
private TerminologyServiceErrorClass errorClass;
|
||||||
private String txLink;
|
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) {
|
public ValidationResult(IssueSeverity severity, String message) {
|
||||||
this.severity = severity;
|
this.severity = severity;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
@ -583,6 +589,10 @@ public interface IWorkerContext {
|
||||||
return definition == null ? null : definition.getCode();
|
return definition == null ? null : definition.getCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDefinition() {
|
||||||
|
return definition == null ? null : definition.getDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
public ConceptDefinitionComponent asConceptDefinition() {
|
public ConceptDefinitionComponent asConceptDefinition() {
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
@ -671,7 +681,7 @@ public interface IWorkerContext {
|
||||||
* @param display - equals Coding.display (optional)
|
* @param display - equals Coding.display (optional)
|
||||||
* @return
|
* @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
|
* Validation of a code - consult the terminology infrstructure and/or service
|
||||||
|
@ -688,7 +698,7 @@ public interface IWorkerContext {
|
||||||
* @param vs the applicable valueset (optional)
|
* @param vs the applicable valueset (optional)
|
||||||
* @return
|
* @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
|
* Validation of a code - consult the terminology infrstructure and/or service
|
||||||
|
|
|
@ -124,6 +124,9 @@ public class TerminologyCache {
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
caches.clear();
|
||||||
|
}
|
||||||
public CacheToken generateValidationToken(ValidationOptions options, Coding code, ValueSet vs) {
|
public CacheToken generateValidationToken(ValidationOptions options, Coding code, ValueSet vs) {
|
||||||
CacheToken ct = new CacheToken();
|
CacheToken ct = new CacheToken();
|
||||||
if (code.hasSystem())
|
if (code.hasSystem())
|
||||||
|
@ -337,11 +340,36 @@ public class TerminologyCache {
|
||||||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.e.getError()).trim()+"\"\r\n}\r\n");
|
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.e.getError()).trim()+"\"\r\n}\r\n");
|
||||||
} else {
|
} else {
|
||||||
sw.write("v: {\r\n");
|
sw.write("v: {\r\n");
|
||||||
sw.write(" \"display\" : \""+Utilities.escapeJson(ce.v.getDisplay()).trim()+"\",\r\n");
|
boolean first = true;
|
||||||
sw.write(" \"code\" : \""+Utilities.escapeJson(ce.v.getCode()).trim()+"\",\r\n");
|
if (ce.v.getDisplay() != null) {
|
||||||
sw.write(" \"system\" : \""+Utilities.escapeJson(ce.v.getSystem()).trim()+"\",\r\n");
|
if (first) first = false; else sw.write(",\r\n");
|
||||||
sw.write(" \"severity\" : "+(ce.v.getSeverity() == null ? "null" : "\""+ce.v.getSeverity().toCode().trim()+"\"")+",\r\n");
|
sw.write(" \"display\" : \""+Utilities.escapeJson(ce.v.getDisplay()).trim()+"\"");
|
||||||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.v.getMessage()).trim()+"\"\r\n}\r\n");
|
}
|
||||||
|
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");
|
sw.write(ENTRY_MARKER+"\r\n");
|
||||||
}
|
}
|
||||||
|
@ -386,11 +414,15 @@ public class TerminologyCache {
|
||||||
else
|
else
|
||||||
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN);
|
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN);
|
||||||
} else {
|
} 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 display = loadJS(o.get("display"));
|
||||||
String code = loadJS(o.get("code"));
|
String code = loadJS(o.get("code"));
|
||||||
String system = loadJS(o.get("system"));
|
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.map.put(String.valueOf(hashNWS(ce.request)), ce);
|
||||||
nc.list.add(ce);
|
nc.list.add(ce);
|
||||||
|
|
|
@ -605,6 +605,12 @@ public class Coding extends DataType implements IBaseCoding, ICompositeType, ICo
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Coding(String theSystem, String theVersion, String theCode, String theDisplay) {
|
||||||
|
setSystem(theSystem);
|
||||||
|
setVersion(theVersion);
|
||||||
|
setCode(theCode);
|
||||||
|
setDisplay(theDisplay);
|
||||||
|
}
|
||||||
// end addition
|
// end addition
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
tr = tbl.tr();
|
tr = tbl.tr();
|
||||||
XhtmlNode td = tr.td();
|
XhtmlNode td = tr.td();
|
||||||
td.addText(ccl.getCode());
|
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))
|
if (display != null && !isSameCodeAndDisplay(ccl.getCode(), display))
|
||||||
td.tx(" ("+display+")");
|
td.tx(" ("+display+")");
|
||||||
TargetElementComponent ccm = ccl.getTarget().get(0);
|
TargetElementComponent ccm = ccl.getTarget().get(0);
|
||||||
|
@ -152,7 +152,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
td.addText(ccm.getCode());
|
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))
|
if (display != null && !isSameCodeAndDisplay(ccm.getCode(), display))
|
||||||
td.tx(" ("+display+")");
|
td.tx(" ("+display+")");
|
||||||
if (comment)
|
if (comment)
|
||||||
|
@ -217,7 +217,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
td.addText(ccl.getCode());
|
td.addText(ccl.getCode());
|
||||||
else
|
else
|
||||||
td.addText(grp.getSource()+" / "+ccl.getCode());
|
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().style("border-left-width: 0px").tx(display == null ? "" : display);
|
||||||
tr.td().colspan("4").style("background-color: #efefef").tx("(not mapped)");
|
tr.td().colspan("4").style("background-color: #efefef").tx("(not mapped)");
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
td.addText(ccl.getCode());
|
td.addText(ccl.getCode());
|
||||||
else
|
else
|
||||||
td.addText(grp.getSource()+" / "+ccl.getCode());
|
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();
|
td = tr.td();
|
||||||
if (!first)
|
if (!first)
|
||||||
td.style("border-left-width: 0px; border-top-style: none");
|
td.style("border-left-width: 0px; border-top-style: none");
|
||||||
|
@ -283,7 +283,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
td.addText(ccm.getCode());
|
td.addText(ccm.getCode());
|
||||||
else
|
else
|
||||||
td.addText(grp.getTarget()+" / "+ccm.getCode());
|
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);
|
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
|
||||||
|
|
||||||
for (String s : targets.keySet()) {
|
for (String s : targets.keySet()) {
|
||||||
|
@ -408,11 +408,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
private String getDisplay(List<OtherElementComponent> list, String s) {
|
private String getDisplay(List<OtherElementComponent> list, String s) {
|
||||||
for (OtherElementComponent c : list) {
|
for (OtherElementComponent c : list) {
|
||||||
if (s.equals(c.getProperty()))
|
if (s.equals(c.getProperty()))
|
||||||
return getDisplayForConcept(c.getSystem(), c.getValue());
|
return getDisplayForConcept(systemFromCanonical(c.getSystem()), versionFromCanonical(c.getSystem()), c.getValue());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -191,8 +191,8 @@ public class DataRenderer extends Renderer {
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String lookupCode(String system, String code) {
|
private String lookupCode(String system, String version, String code) {
|
||||||
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), system, code, null);
|
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().setVersionFlexible(true), system, version, code, null);
|
||||||
|
|
||||||
if (t != null && t.getDisplay() != null)
|
if (t != null && t.getDisplay() != null)
|
||||||
return t.getDisplay();
|
return t.getDisplay();
|
||||||
|
@ -484,7 +484,7 @@ public class DataRenderer extends Renderer {
|
||||||
if (c.hasDisplayElement())
|
if (c.hasDisplayElement())
|
||||||
return c.getDisplay();
|
return c.getDisplay();
|
||||||
if (Utilities.noString(s))
|
if (Utilities.noString(s))
|
||||||
s = lookupCode(c.getSystem(), c.getCode());
|
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||||
if (Utilities.noString(s))
|
if (Utilities.noString(s))
|
||||||
s = c.getCode();
|
s = c.getCode();
|
||||||
return s;
|
return s;
|
||||||
|
@ -507,7 +507,7 @@ public class DataRenderer extends Renderer {
|
||||||
if (c.hasDisplayElement())
|
if (c.hasDisplayElement())
|
||||||
s = c.getDisplay();
|
s = c.getDisplay();
|
||||||
if (Utilities.noString(s))
|
if (Utilities.noString(s))
|
||||||
s = lookupCode(c.getSystem(), c.getCode());
|
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||||
|
|
||||||
|
|
||||||
String sn = describeSystem(c.getSystem());
|
String sn = describeSystem(c.getSystem());
|
||||||
|
@ -539,13 +539,13 @@ public class DataRenderer extends Renderer {
|
||||||
if (c.hasDisplayElement())
|
if (c.hasDisplayElement())
|
||||||
s = c.getDisplay();
|
s = c.getDisplay();
|
||||||
if (Utilities.noString(s))
|
if (Utilities.noString(s))
|
||||||
s = lookupCode(c.getSystem(), c.getCode());
|
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||||
|
|
||||||
if (Utilities.noString(s))
|
if (Utilities.noString(s))
|
||||||
s = c.getCode();
|
s = c.getCode();
|
||||||
|
|
||||||
if (showCodeDetails) {
|
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
|
} else
|
||||||
x.span(null, "{"+c.getSystem()+" "+c.getCode()+"}").addText(s);
|
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
|
// still? ok, let's try looking it up
|
||||||
for (Coding c : cc.getCoding()) {
|
for (Coding c : cc.getCoding()) {
|
||||||
if (c.hasCode() && c.hasSystem()) {
|
if (c.hasCode() && c.hasSystem()) {
|
||||||
s = lookupCode(c.getSystem(), c.getCode());
|
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||||
if (!Utilities.noString(s))
|
if (!Utilities.noString(s))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -611,7 +611,7 @@ public class DataRenderer extends Renderer {
|
||||||
// still? ok, let's try looking it up
|
// still? ok, let's try looking it up
|
||||||
for (Coding c : cc.getCoding()) {
|
for (Coding c : cc.getCoding()) {
|
||||||
if (c.hasCodeElement() && c.hasSystemElement()) {
|
if (c.hasCodeElement() && c.hasSystemElement()) {
|
||||||
s = lookupCode(c.getSystem(), c.getCode());
|
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
|
||||||
if (!Utilities.noString(s))
|
if (!Utilities.noString(s))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +636,7 @@ public class DataRenderer extends Renderer {
|
||||||
first = false;
|
first = false;
|
||||||
} else
|
} else
|
||||||
sp.tx("; ");
|
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(")");
|
sp.tx(")");
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,7 +661,7 @@ public class DataRenderer extends Renderer {
|
||||||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay())
|
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay())
|
||||||
s = ii.getType().getCoding().get(0).getDisplay()+": "+s;
|
s = ii.getType().getCoding().get(0).getDisplay()+": "+s;
|
||||||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode())
|
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 {
|
} else {
|
||||||
s = "id: "+s;
|
s = "id: "+s;
|
||||||
}
|
}
|
||||||
|
@ -838,7 +838,7 @@ public class DataRenderer extends Renderer {
|
||||||
|
|
||||||
s.append("(system = '").append(TerminologyRenderer.describeSystem(q.getSystem()))
|
s.append("(system = '").append(TerminologyRenderer.describeSystem(q.getSystem()))
|
||||||
.append("' code ").append(q.getCode())
|
.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();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
@ -858,7 +858,7 @@ public class DataRenderer extends Renderer {
|
||||||
else if (q.hasCode())
|
else if (q.hasCode())
|
||||||
x.tx(" "+q.getCode());
|
x.tx(" "+q.getCode());
|
||||||
if (showCodeDetails && q.hasCode()) {
|
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();
|
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)
|
if (value == null || system == null)
|
||||||
return 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();
|
return cl == null ? null : cl.getDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -896,7 +896,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
li.ah(href).addText(f.getValue());
|
li.ah(href).addText(f.getValue());
|
||||||
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
||||||
li.addText(f.getValue());
|
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()) {
|
if (vr.isOk()) {
|
||||||
li.tx(" ("+vr.getDisplay()+")");
|
li.tx(" ("+vr.getDisplay()+")");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,11 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.exceptions.PathEngineException;
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
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.Base;
|
||||||
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
||||||
import org.hl7.fhir.r5.model.BooleanType;
|
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.Constants;
|
||||||
import org.hl7.fhir.r5.model.DateTimeType;
|
import org.hl7.fhir.r5.model.DateTimeType;
|
||||||
import org.hl7.fhir.r5.model.DateType;
|
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;
|
||||||
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
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.FHIRLexer.FHIRLexerException;
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
|
||||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
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 {
|
private List<Base> opMemberOf(ExecutionContext context, List<Base> left, List<Base> right, ExpressionNode expr) throws FHIRException {
|
||||||
boolean ans = false;
|
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) {
|
if (vs != null) {
|
||||||
for (Base l : left) {
|
for (Base l : left) {
|
||||||
if (Utilities.existsInList(l.fhirType(), "code", "string", "uri")) {
|
if (Utilities.existsInList(l.fhirType(), "code", "string", "uri")) {
|
||||||
|
@ -2341,7 +2345,10 @@ public class FHIRPathEngine {
|
||||||
ans = true;
|
ans = true;
|
||||||
}
|
}
|
||||||
} else if (l.fhirType().equals("CodeableConcept")) {
|
} 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;
|
ans = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -322,16 +322,9 @@ public class NPMPackageGenerator {
|
||||||
|
|
||||||
public void addFile(Category cat, String name, byte[] content) throws IOException {
|
public void addFile(Category cat, String name, byte[] content) throws IOException {
|
||||||
String path = cat.getDirectory()+name;
|
String path = cat.getDirectory()+name;
|
||||||
if (!path.startsWith("package/")) {
|
|
||||||
path = "package/" +path;
|
|
||||||
}
|
|
||||||
if (path.length() > 100) {
|
if (path.length() > 100) {
|
||||||
name = name.substring(0, name.indexOf("-"))+"-"+UUID.randomUUID().toString();
|
name = name.substring(0, name.indexOf("-"))+"-"+UUID.randomUUID().toString();
|
||||||
path = cat.getDirectory()+name;
|
path = cat.getDirectory()+name;
|
||||||
if (!path.startsWith("package/")) {
|
|
||||||
path = "package/" +path;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created.contains(path)) {
|
if (created.contains(path)) {
|
||||||
|
|
|
@ -1752,6 +1752,7 @@ public class StructureMapUtilities {
|
||||||
// if we can get this as a valueSet, we will
|
// if we can get this as a valueSet, we will
|
||||||
String system = null;
|
String system = null;
|
||||||
String display = null;
|
String display = null;
|
||||||
|
String version = null;
|
||||||
ValueSet vs = Utilities.noString(uri) ? null : worker.fetchResourceWithException(ValueSet.class, uri);
|
ValueSet vs = Utilities.noString(uri) ? null : worker.fetchResourceWithException(ValueSet.class, uri);
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
ValueSetExpansionOutcome vse = worker.expandVS(vs, true, false);
|
ValueSetExpansionOutcome vse = worker.expandVS(vs, true, false);
|
||||||
|
@ -1763,20 +1764,23 @@ public class StructureMapUtilities {
|
||||||
b.append(t.getCode());
|
b.append(t.getCode());
|
||||||
if (code.equals(t.getCode()) && t.hasSystem()) {
|
if (code.equals(t.getCode()) && t.hasSystem()) {
|
||||||
system = t.getSystem();
|
system = t.getSystem();
|
||||||
|
version = t.getVersion();
|
||||||
display = t.getDisplay();
|
display = t.getDisplay();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (code.equalsIgnoreCase(t.getDisplay()) && t.hasSystem()) {
|
if (code.equalsIgnoreCase(t.getDisplay()) && t.hasSystem()) {
|
||||||
system = t.getSystem();
|
system = t.getSystem();
|
||||||
|
version = t.getVersion();
|
||||||
display = t.getDisplay();
|
display = t.getDisplay();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (system == null)
|
if (system == null)
|
||||||
throw new FHIRException("The code '" + code + "' is not in the value set '" + uri + "' (valid codes: " + b.toString() + "; also checked displays)");
|
throw new FHIRException("The code '" + code + "' is not in the value set '" + uri + "' (valid codes: " + b.toString() + "; also checked displays)");
|
||||||
} else
|
} else {
|
||||||
system = uri;
|
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)
|
if (vr != null && vr.getDisplay() != null)
|
||||||
display = vr.getDisplay();
|
display = vr.getDisplay();
|
||||||
return new Coding().setSystem(system).setCode(code).setDisplay(display);
|
return new Coding().setSystem(system).setCode(code).setDisplay(display);
|
||||||
|
|
|
@ -1,5 +1,37 @@
|
||||||
package org.hl7.fhir.utilities;
|
package org.hl7.fhir.utilities;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
@ -33,41 +65,9 @@ package org.hl7.fhir.utilities;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipInputStream;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
|
|
||||||
public class Utilities {
|
public class Utilities {
|
||||||
|
|
||||||
|
private static final String UUID_REGEX = "[0-9a-f]{8}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{12}";
|
||||||
private static final String OID_REGEX = "[0-2](\\.(0|[1-9][0-9]*))+";
|
private static final String OID_REGEX = "[0-2](\\.(0|[1-9][0-9]*))+";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1476,7 +1476,7 @@ public class Utilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
|
final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Arrays.sort(illegalChars);
|
Arrays.sort(illegalChars);
|
||||||
}
|
}
|
||||||
|
@ -1493,5 +1493,13 @@ public class Utilities {
|
||||||
return cleanName.toString();
|
return cleanName.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isValidUUID(String uuid) {
|
||||||
|
return uuid.matches(UUID_REGEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidOID(String oid) {
|
||||||
|
return oid.matches(OID_REGEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -105,8 +105,10 @@ public class I18nConstants {
|
||||||
public static final String ERROR_READING__FROM_PACKAGE__ = "Error_reading__from_package__";
|
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_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 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_EXTP_CONTEXT_WRONG = "Extension_EXTP_Context_Wrong";
|
||||||
public static final String EXTENSION_EXT_CONTEXT_WRONG_XVER = "EXTENSION_EXT_CONTEXT_WRONG_XVER";
|
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_MISMATCH = "Extension_EXT_Count_Mismatch";
|
||||||
public static final String EXTENSION_EXT_COUNT_NOTFOUND = "Extension_EXT_Count_NotFound";
|
public static final String EXTENSION_EXT_COUNT_NOTFOUND = "Extension_EXT_Count_NotFound";
|
||||||
public static final String EXTENSION_EXT_FIXED_BANNED = "Extension_EXT_Fixed_Banned";
|
public static final String EXTENSION_EXT_FIXED_BANNED = "Extension_EXT_Fixed_Banned";
|
||||||
|
@ -459,6 +461,7 @@ public class I18nConstants {
|
||||||
public static final String TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT = "type_on_first_differential_element";
|
public static final String TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT = "type_on_first_differential_element";
|
||||||
public static final String TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_ = "type_on_first_snapshot_element_for__in__from_";
|
public static final String TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_ = "type_on_first_snapshot_element_for__in__from_";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = "TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE";
|
public static final String TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = "TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_CANONICAL_CONTAINED = "TYPE_SPECIFIC_CHECKS_CANONICAL_CONTAINED";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_NO_CONTENT = "TYPE_SPECIFIC_CHECKS_DT_ATT_NO_CONTENT";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_NO_CONTENT = "TYPE_SPECIFIC_CHECKS_DT_ATT_NO_CONTENT";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER = "TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER = "TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_SIZE_CORRECT = "TYPE_SPECIFIC_CHECKS_DT_ATT_SIZE_CORRECT";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_ATT_SIZE_CORRECT = "TYPE_SPECIFIC_CHECKS_DT_ATT_SIZE_CORRECT";
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class ValidationOptions {
|
||||||
private boolean guessSystem = false;
|
private boolean guessSystem = false;
|
||||||
private ValueSetMode valueSetMode = ValueSetMode.ALL_CHECKS;
|
private ValueSetMode valueSetMode = ValueSetMode.ALL_CHECKS;
|
||||||
private boolean vsAsUrl;
|
private boolean vsAsUrl;
|
||||||
|
private boolean versionFlexible = true;
|
||||||
|
|
||||||
public ValidationOptions() {
|
public ValidationOptions() {
|
||||||
super();
|
super();
|
||||||
|
@ -45,6 +46,7 @@ public class ValidationOptions {
|
||||||
n.useClient = useClient;
|
n.useClient = useClient;
|
||||||
n.guessSystem = guessSystem;
|
n.guessSystem = guessSystem;
|
||||||
n.vsAsUrl = vsAsUrl;
|
n.vsAsUrl = vsAsUrl;
|
||||||
|
n.versionFlexible = versionFlexible;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +77,8 @@ public class ValidationOptions {
|
||||||
|
|
||||||
|
|
||||||
public String toJson() {
|
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() {
|
public static ValidationOptions defaults() {
|
||||||
|
@ -107,5 +110,15 @@ public class ValidationOptions {
|
||||||
return vsAsUrl;
|
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_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_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})
|
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_Mismatch = Extensions count mismatch: expected {0} but found {1}
|
||||||
Extension_EXT_Count_NotFound = Extension count mismatch: unable to find extension: {0}
|
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
|
Extension_EXT_Fixed_Banned = No extensions allowed, as the specified fixed value doesn''t contain any extensions
|
||||||
|
@ -207,7 +208,7 @@ Type_Specific_Checks_DT_URI_UUID = URI values cannot start with uuid:
|
||||||
Type_Specific_Checks_DT_URI_WS = URI values cannot have whitespace(''{0}'')
|
Type_Specific_Checks_DT_URI_WS = URI values cannot have whitespace(''{0}'')
|
||||||
Type_Specific_Checks_DT_URL_Resolve = URL value ''{0}'' does not resolve
|
Type_Specific_Checks_DT_URL_Resolve = URL value ''{0}'' does not resolve
|
||||||
Type_Specific_Checks_DT_UUID_Strat = UUIDs must start with urn:uuid:
|
Type_Specific_Checks_DT_UUID_Strat = UUIDs must start with urn:uuid:
|
||||||
Type_Specific_Checks_DT_UUID_Vaid = UUIDs must be valid ({0})
|
Type_Specific_Checks_DT_UUID_Vaid = UUIDs must be valid
|
||||||
Validation_BUNDLE_Message = The first entry in a message must be a MessageHeader
|
Validation_BUNDLE_Message = The first entry in a message must be a MessageHeader
|
||||||
Validation_VAL_Content_Unknown = Unrecognised Content {0}
|
Validation_VAL_Content_Unknown = Unrecognised Content {0}
|
||||||
Validation_VAL_NoType = Unknown type {0}
|
Validation_VAL_NoType = Unknown type {0}
|
||||||
|
@ -468,7 +469,8 @@ MEASURE_M_GROUP_POP_NO_CODE = A measure group population should have a code when
|
||||||
MEASURE_M_GROUP_STRATA_NO_CODE = A measure group stratifier should have a code when there is more than one population
|
MEASURE_M_GROUP_STRATA_NO_CODE = A measure group stratifier should have a code when there is more than one population
|
||||||
MEASURE_M_GROUP_STRATA_COMP_NO_CODE = A measure group stratifier component should have a code when there is more than one population
|
MEASURE_M_GROUP_STRATA_COMP_NO_CODE = A measure group stratifier component should have a code when there is more than one population
|
||||||
MEASURE_M_LIB_UNKNOWN = The Library {0} could not be resolved, so expression validation may not be correct
|
MEASURE_M_LIB_UNKNOWN = The Library {0} could not be resolved, so expression validation may not be correct
|
||||||
TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = Canonical URLs must be absolute URLs if they are not fragment references ({0})
|
TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = Canonical URLs must be absolute URLs if they are not fragment references ({0})
|
||||||
|
TYPE_SPECIFIC_CHECKS_CANONICAL_CONTAINED = Canonical URLs in contained resources must be absolute URLs if present ({0})
|
||||||
MEASURE_MR_SCORE_PROHIBITED_RT = No measureScore when the type of the report is ''data-collection''
|
MEASURE_MR_SCORE_PROHIBITED_RT = No measureScore when the type of the report is ''data-collection''
|
||||||
MEASURE_MR_SCORE_PROHIBITED_MS = No measureScore when the scoring of the mesage is ''cohort''
|
MEASURE_MR_SCORE_PROHIBITED_MS = No measureScore when the scoring of the mesage is ''cohort''
|
||||||
MEASURE_MR_SCORE_REQUIRED = A measureScore is required when the Measure.scoring={0}
|
MEASURE_MR_SCORE_REQUIRED = A measureScore is required when the Measure.scoring={0}
|
||||||
|
@ -505,7 +507,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_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_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}
|
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_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
|
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
|
ALL_OK = All OK
|
||||||
|
|
|
@ -1007,4 +1007,24 @@ public class BaseValidator {
|
||||||
}
|
}
|
||||||
return null;
|
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 List<BundleValidationRule> bundleValidationRules = new ArrayList<>();
|
||||||
private boolean validateValueSetCodesOnTxServer = true;
|
private boolean validateValueSetCodesOnTxServer = true;
|
||||||
private QuestionnaireMode questionnaireMode;
|
private QuestionnaireMode questionnaireMode;
|
||||||
|
private ValidationOptions baseOptions = new ValidationOptions();
|
||||||
|
|
||||||
public InstanceValidator(IWorkerContext theContext, IEvaluationContext hostServices, XVerExtensionManager xverManager) {
|
public InstanceValidator(IWorkerContext theContext, IEvaluationContext hostServices, XVerExtensionManager xverManager) {
|
||||||
super(theContext, xverManager);
|
super(theContext, xverManager);
|
||||||
|
@ -836,13 +837,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
// public API
|
// 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();
|
long t = System.nanoTime();
|
||||||
boolean ss = context.supportsSystem(system);
|
boolean ss = context.supportsSystem(system);
|
||||||
timeTracker.tx(t, "ss "+system);
|
timeTracker.tx(t, "ss "+system);
|
||||||
if (ss) {
|
if (ss) {
|
||||||
t = System.nanoTime();
|
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+"'");
|
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1251,8 +1252,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
for (Coding nextCoding : cc.getCoding()) {
|
for (Coding nextCoding : cc.getCoding()) {
|
||||||
String nextCode = nextCoding.getCode();
|
String nextCode = nextCoding.getCode();
|
||||||
String nextSystem = nextCoding.getSystem();
|
String nextSystem = nextCoding.getSystem();
|
||||||
|
String nextVersion = nextCoding.getVersion();
|
||||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
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()) {
|
if (!vr.isOk()) {
|
||||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_NOTVALID, nextCode, nextSystem);
|
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 code = c.getCode();
|
||||||
String system = c.getSystem();
|
String system = c.getSystem();
|
||||||
String display = c.getDisplay();
|
String display = c.getDisplay();
|
||||||
|
String version = c.getVersion();
|
||||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
|
||||||
|
|
||||||
if (system != null && code != null && !noTerminologyChecks) {
|
if (system != null && code != null && !noTerminologyChecks) {
|
||||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
|
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
|
||||||
try {
|
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()) {
|
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
|
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))) {
|
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(maxVSUrl))) {
|
||||||
try {
|
try {
|
||||||
long t = System.nanoTime();
|
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);
|
timeTracker.tx(t, "vc "+value);
|
||||||
if (!vr.isOk()) {
|
if (!vr.isOk()) {
|
||||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
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) {
|
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 code = element.getNamedChildValue("code");
|
||||||
String system = element.getNamedChildValue("system");
|
String system = element.getNamedChildValue("system");
|
||||||
|
String version = element.getNamedChildValue("version");
|
||||||
String display = element.getNamedChildValue("display");
|
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,
|
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);
|
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);
|
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) {
|
if (theSystem != null && theCode != null && !noTerminologyChecks) {
|
||||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, theSystem);
|
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, theSystem);
|
||||||
try {
|
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()) {
|
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
|
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
|
// two questions
|
||||||
// 1. can this extension be used here?
|
// 1. can this extension be used here?
|
||||||
checkExtensionContext(errors, resource, container, ex, containerStack, hostContext);
|
checkExtensionContext(errors, resource, container, ex, containerStack, hostContext, isModifier);
|
||||||
|
|
||||||
if (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);
|
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;
|
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();
|
String extUrl = definition.getUrl();
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
CommaSeparatedStringBuilder contexts = new CommaSeparatedStringBuilder();
|
CommaSeparatedStringBuilder contexts = new CommaSeparatedStringBuilder();
|
||||||
|
@ -1774,9 +1778,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (definition.hasUserData(XVerExtensionManager.XVER_EXT_MARKER)) {
|
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 {
|
} 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;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2019,23 +2025,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !context.hasMaxLength() || context.getMaxLength() == 0 || e.primitiveValue().length() <= context.getMaxLength(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_LENGTH, context.getMaxLength());
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !context.hasMaxLength() || context.getMaxLength() == 0 || e.primitiveValue().length() <= context.getMaxLength(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_LENGTH, context.getMaxLength());
|
||||||
|
|
||||||
if (type.equals("oid")) {
|
if (type.equals("oid")) {
|
||||||
if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("urn:oid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_OID_START))
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("urn:oid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_OID_START);
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, Utilities.isOid(url.substring(8)), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_OID_VALID);
|
|
||||||
}
|
}
|
||||||
if (type.equals("uuid")) {
|
if (type.equals("uuid")) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("urn:uuid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_UUID_STRAT);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("urn:uuid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_UUID_STRAT);
|
||||||
try {
|
|
||||||
UUID.fromString(url.substring(8));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_UUID_VAID, ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (type.equals("canonical")) {
|
if (type.equals("canonical")) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("#") || Utilities.isAbsoluteUrl(url), I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE, url);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("#") || Utilities.isAbsoluteUrl(url), I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (url != null && url.startsWith("urn:uuid:")) {
|
||||||
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, Utilities.isValidUUID(url.substring(9)), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_UUID_VAID);
|
||||||
|
}
|
||||||
|
if (url != null && url.startsWith("urn:oid:")) {
|
||||||
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, Utilities.isOid(url.substring(8)), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_OID_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
if (isCanonicalURLElement(e)) {
|
if (isCanonicalURLElement(e)) {
|
||||||
// for now, no validation. Need to think about authority.
|
// we get to here if this is a defining canonical URL (e.g. CodeSystem.url)
|
||||||
|
// the URL must be an IRI if present
|
||||||
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, Utilities.isAbsoluteUrl(url),
|
||||||
|
node.isContained() ? I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_CONTAINED : I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE, url);
|
||||||
} else {
|
} else {
|
||||||
// now, do we check the URI target?
|
// now, do we check the URI target?
|
||||||
if (fetcher != null && !type.equals("uuid")) {
|
if (fetcher != null && !type.equals("uuid")) {
|
||||||
|
@ -2484,7 +2494,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
long t = System.nanoTime();
|
long t = System.nanoTime();
|
||||||
ValidationResult vr = null;
|
ValidationResult vr = null;
|
||||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
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);
|
vr = checkCodeOnServer(stack, vs, value, options);
|
||||||
}
|
}
|
||||||
timeTracker.tx(t, "vc "+value+"");
|
timeTracker.tx(t, "vc "+value+"");
|
||||||
|
@ -2543,7 +2553,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system != null || code != null ) {
|
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)) {
|
if (code != null && "http://unitsofmeasure.org".equals(system)) {
|
||||||
|
@ -4188,7 +4198,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
} else if (element.getType().equals("CapabilityStatement")) {
|
} else if (element.getType().equals("CapabilityStatement")) {
|
||||||
validateCapabilityStatement(errors, element, stack);
|
validateCapabilityStatement(errors, element, stack);
|
||||||
} else if (element.getType().equals("CodeSystem")) {
|
} 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")) {
|
} else if (element.getType().equals("SearchParameter")) {
|
||||||
new SearchParameterValidator(context, timeTracker, fpe, xverManager).validateSearchParameter(errors, element, stack);
|
new SearchParameterValidator(context, timeTracker, fpe, xverManager).validateSearchParameter(errors, element, stack);
|
||||||
} else if (element.getType().equals("StructureDefinition")) {
|
} else if (element.getType().equals("StructureDefinition")) {
|
||||||
|
@ -4311,6 +4321,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
idstatus = IdStatus.OPTIONAL;
|
idstatus = IdStatus.OPTIONAL;
|
||||||
break;
|
break;
|
||||||
case CONTAINED:
|
case CONTAINED:
|
||||||
|
stack.setContained(true);
|
||||||
idstatus = IdStatus.REQUIRED;
|
idstatus = IdStatus.REQUIRED;
|
||||||
break;
|
break;
|
||||||
case PARAMETER:
|
case PARAMETER:
|
||||||
|
@ -4405,7 +4416,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (definition.getPath().equals("StructureDefinition.snapshot")) {
|
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();
|
stack.resetIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4993,6 +5004,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
} else {
|
} else {
|
||||||
if (nameMatches(ei.getName(), tail(ed.getPath())))
|
if (nameMatches(ei.getName(), tail(ed.getPath())))
|
||||||
try {
|
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);
|
match = sliceMatches(hostContext, ei.getElement(), ei.getPath(), slicer, ed, profile, errors, sliceInfo, stack, profile);
|
||||||
if (match) {
|
if (match) {
|
||||||
ei.slice = slicer;
|
ei.slice = slicer;
|
||||||
|
@ -5026,6 +5038,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return unsupportedSlicing;
|
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 {
|
private ElementDefinition getElementByTail(StructureDefinition p, String tail) throws DefinitionException {
|
||||||
if (tail == null)
|
if (tail == null)
|
||||||
return p.getSnapshot().getElement().get(0);
|
return p.getSnapshot().getElement().get(0);
|
||||||
|
@ -5349,6 +5377,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if ("probability is decimal implies (probability as decimal) <= 100".equals(expr)) {
|
if ("probability is decimal implies (probability as decimal) <= 100".equals(expr)) {
|
||||||
return "probablility.empty() or ((probability is decimal) implies ((probability as decimal) <= 100))";
|
return "probablility.empty() or ((probability is decimal) implies ((probability as decimal) <= 100))";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("enableWhen.count() > 2 implies enableBehavior.exists()".equals(expr)) {
|
if ("enableWhen.count() > 2 implies enableBehavior.exists()".equals(expr)) {
|
||||||
return "enableWhen.count() >= 2 implies enableBehavior.exists()";
|
return "enableWhen.count() >= 2 implies enableBehavior.exists()";
|
||||||
}
|
}
|
||||||
|
@ -5451,23 +5480,23 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
// no delay on this one?
|
// no delay on this one?
|
||||||
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String display, boolean checkDisplay) {
|
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String version, String display, boolean checkDisplay) {
|
||||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()), system, code, checkDisplay ? display : null);
|
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()), system, version, code, checkDisplay ? display : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, Coding c, boolean checkMembership) {
|
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, Coding c, boolean checkMembership) {
|
||||||
if (checkMembership) {
|
if (checkMembership) {
|
||||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).checkValueSetOnly(), c, valueset);
|
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()).checkValueSetOnly(), c, valueset);
|
||||||
} else {
|
} 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) {
|
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc, boolean vsOnly) {
|
||||||
if (vsOnly) {
|
if (vsOnly) {
|
||||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).checkValueSetOnly(), cc, valueset);
|
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()).checkValueSetOnly(), cc, valueset);
|
||||||
} else {
|
} else {
|
||||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()), cc, valueset);
|
return context.validateCode(baseOptions.setLanguage(stack.getWorkingLang()), cc, valueset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5534,4 +5563,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
this.wantCheckSnapshotUnchanged = wantCheckSnapshotUnchanged;
|
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) {
|
private void validateSupplementConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String supp, ValidationOptions options) {
|
||||||
String code = concept.getChildValue("code");
|
String code = concept.getChildValue("code");
|
||||||
if (!Utilities.noString(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);
|
rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class NodeStack {
|
||||||
private String workingLang;
|
private String workingLang;
|
||||||
private Map<String, Element> ids;
|
private Map<String, Element> ids;
|
||||||
private boolean resetPoint = false;
|
private boolean resetPoint = false;
|
||||||
|
private boolean contained = false;
|
||||||
|
|
||||||
public NodeStack(IWorkerContext context) {
|
public NodeStack(IWorkerContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -101,6 +102,7 @@ public class NodeStack {
|
||||||
res.workingLang = this.workingLang;
|
res.workingLang = this.workingLang;
|
||||||
res.element = element;
|
res.element = element;
|
||||||
res.definition = definition;
|
res.definition = definition;
|
||||||
|
res.contained = contained;
|
||||||
res.literalPath = getLiteralPath() + sep + element.getName();
|
res.literalPath = getLiteralPath() + sep + element.getName();
|
||||||
if (count > -1)
|
if (count > -1)
|
||||||
res.literalPath = res.literalPath + "[" + Integer.toString(count) + "]";
|
res.literalPath = res.literalPath + "[" + Integer.toString(count) + "]";
|
||||||
|
@ -195,5 +197,13 @@ public class NodeStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isContained() {
|
||||||
|
return contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContained(boolean contained) {
|
||||||
|
this.contained = contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -173,6 +173,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
val.setWantCheckSnapshotUnchanged(true);
|
val.setWantCheckSnapshotUnchanged(true);
|
||||||
val.getContext().setClientRetryCount(4);
|
val.getContext().setClientRetryCount(4);
|
||||||
val.setDebug(false);
|
val.setDebug(false);
|
||||||
|
|
||||||
if (content.has("fetcher") && "standalone".equals(JSONUtil.str(content, "fetcher"))) {
|
if (content.has("fetcher") && "standalone".equals(JSONUtil.str(content, "fetcher"))) {
|
||||||
val.setFetcher(vCurr);
|
val.setFetcher(vCurr);
|
||||||
vCurr.setFetcher(new StandAloneValidatorFetcher(vCurr.getPcm(), vCurr.getContext(), 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());
|
val.setValidationLanguage(content.get("language").getAsString());
|
||||||
else
|
else
|
||||||
val.setValidationLanguage(null);
|
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")) {
|
if (content.has("packages")) {
|
||||||
for (JsonElement e : content.getAsJsonArray("packages")) {
|
for (JsonElement e : content.getAsJsonArray("packages")) {
|
||||||
String n = e.getAsString();
|
String n = e.getAsString();
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||||
<validator_test_case_version>1.1.69</validator_test_case_version>
|
<validator_test_case_version>1.1.70-SNAPSHOT</validator_test_case_version>
|
||||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||||
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
||||||
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
||||||
|
|
Loading…
Reference in New Issue