improved npe safety formatMessage method

This commit is contained in:
patrick-werner 2020-03-10 16:03:50 +01:00
parent 14a0f7d687
commit 7ada30807d
5 changed files with 393 additions and 248 deletions

View File

@ -425,13 +425,13 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
String message = theMessage;
if (Objects.nonNull(i18Nmessages) && i18Nmessages.containsKey(theMessage)) {
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
} else {
message = theMessage;
message = i18Nmessages.getString(theMessage);
}
}
return message;
}

View File

@ -464,13 +464,13 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
String message = theMessage;
if (Objects.nonNull(i18Nmessages) && i18Nmessages.containsKey(theMessage)) {
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
} else {
message = theMessage;
message = i18Nmessages.getString(theMessage);
}
}
return message;
}

View File

@ -162,8 +162,9 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
public void seeExtensionDefinition(String url, StructureDefinition ed) throws Exception {
if (extensionDefinitions.get(ed.getUrl()) != null)
if (extensionDefinitions.get(ed.getUrl()) != null) {
throw new Exception("duplicate extension definition: " + ed.getUrl());
}
extensionDefinitions.put(ed.getId(), ed);
extensionDefinitions.put(url, ed);
extensionDefinitions.put(ed.getUrl(), ed);
@ -172,27 +173,31 @@ public abstract class BaseWorkerContext implements IWorkerContext {
public void dropExtensionDefinition(String id) {
StructureDefinition sd = extensionDefinitions.get(id);
extensionDefinitions.remove(id);
if (sd!= null)
if (sd != null) {
extensionDefinitions.remove(sd.getUrl());
}
}
public void seeQuestionnaire(String url, Questionnaire theQuestionnaire) throws Exception {
if (questionnaires.get(theQuestionnaire.getId()) != null)
if (questionnaires.get(theQuestionnaire.getId()) != null) {
throw new Exception("duplicate extension definition: " + theQuestionnaire.getId());
}
questionnaires.put(theQuestionnaire.getId(), theQuestionnaire);
questionnaires.put(url, theQuestionnaire);
}
public void seeOperation(OperationDefinition opd) throws Exception {
if (operations.get(opd.getUrl()) != null)
if (operations.get(opd.getUrl()) != null) {
throw new Exception("duplicate extension definition: " + opd.getUrl());
}
operations.put(opd.getUrl(), opd);
operations.put(opd.getId(), opd);
}
public void seeValueSet(String url, ValueSet vs) throws Exception {
if (valueSets.containsKey(vs.getUrl()) && !allowLoadingDuplicates)
if (valueSets.containsKey(vs.getUrl()) && !allowLoadingDuplicates) {
throw new Exception("Duplicate value set " + vs.getUrl());
}
valueSets.put(vs.getId(), vs);
valueSets.put(url, vs);
valueSets.put(vs.getUrl(), vs);
@ -201,13 +206,15 @@ public abstract class BaseWorkerContext implements IWorkerContext {
public void dropValueSet(String id) {
ValueSet vs = valueSets.get(id);
valueSets.remove(id);
if (vs != null)
if (vs != null) {
valueSets.remove(vs.getUrl());
}
}
public void seeCodeSystem(String url, CodeSystem cs) throws FHIRException {
if (codeSystems.containsKey(cs.getUrl()) && !allowLoadingDuplicates)
if (codeSystems.containsKey(cs.getUrl()) && !allowLoadingDuplicates) {
throw new FHIRException("Duplicate code system " + cs.getUrl());
}
codeSystems.put(cs.getId(), cs);
codeSystems.put(url, cs);
codeSystems.put(cs.getUrl(), cs);
@ -216,13 +223,15 @@ public abstract class BaseWorkerContext implements IWorkerContext {
public void dropCodeSystem(String id) {
CodeSystem cs = codeSystems.get(id);
codeSystems.remove(id);
if (cs != null)
if (cs != null) {
codeSystems.remove(cs.getUrl());
}
}
public void seeProfile(String url, StructureDefinition p) throws Exception {
if (profiles.containsKey(p.getUrl()))
if (profiles.containsKey(p.getUrl())) {
throw new Exception("Duplicate Profile " + p.getUrl());
}
profiles.put(p.getId(), p);
profiles.put(url, p);
profiles.put(p.getUrl(), p);
@ -231,9 +240,10 @@ public abstract class BaseWorkerContext implements IWorkerContext {
public void dropProfile(String id) {
StructureDefinition sd = profiles.get(id);
profiles.remove(id);
if (sd!= null)
if (sd != null) {
profiles.remove(sd.getUrl());
}
}
@Override
public CodeSystem fetchCodeSystem(String system) {
@ -242,28 +252,33 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public boolean supportsSystem(String system) throws TerminologyServiceException {
if (codeSystems.containsKey(system))
if (codeSystems.containsKey(system)) {
return true;
else if (nonSupportedCodeSystems.contains(system))
} else if (nonSupportedCodeSystems.contains(system)) {
return false;
else if (system.startsWith("http://example.org") || system.startsWith("http://acme.com") || system.startsWith("http://hl7.org/fhir/valueset-") || system.startsWith("urn:oid:"))
} else if (system.startsWith("http://example.org") || system.startsWith("http://acme.com")
|| system.startsWith("http://hl7.org/fhir/valueset-") || system.startsWith("urn:oid:")) {
return false;
else {
if (noTerminologyServer)
} else {
if (noTerminologyServer) {
return false;
}
if (bndCodeSystems == null) {
try {
tlog("Terminology server: Check for supported code systems for " + system);
bndCodeSystems = txServer.fetchFeed(txServer.getAddress()+"/CodeSystem?content-mode=not-present&_summary=true&_count=1000");
bndCodeSystems = txServer.fetchFeed(txServer.getAddress()
+ "/CodeSystem?content-mode=not-present&_summary=true&_count=1000");
} catch (Exception e) {
if (canRunWithoutTerminology) {
noTerminologyServer = true;
log("==============!! Running without terminology server !!============== ("+e.getMessage()+")");
log("==============!! Running without terminology server !!============== (" + e
.getMessage() + ")");
return false;
} else
} else {
throw new TerminologyServiceException(e);
}
}
}
if (bndCodeSystems != null) {
for (BundleEntryComponent be : bndCodeSystems.getEntry()) {
CodeSystem cs = (CodeSystem) be.getResource();
@ -272,19 +287,21 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
}
}
if (codeSystems.containsKey(system))
if (codeSystems.containsKey(system)) {
return true;
}
}
nonSupportedCodeSystems.add(system);
return false;
}
private void log(String message) {
if (logger != null)
if (logger != null) {
logger.logMessage(message);
else
} else {
System.out.println(message);
}
}
@Override
public ValueSetExpansionOutcome expandVS(ValueSet vs, boolean cacheOk, boolean heirarchical) {
@ -295,13 +312,16 @@ public abstract class BaseWorkerContext implements IWorkerContext {
String cacheFn = null;
if (cache != null) {
cacheFn = Utilities.path(cache, determineCacheId(vs, heirarchical) + ".json");
if (new File(cacheFn).exists())
if (new File(cacheFn).exists()) {
return loadFromCache(vs.copy(), cacheFn);
}
}
if (cacheOk && vs.hasUrl()) {
if (expProfile == null)
if (expProfile == null) {
throw new Exception("No ExpansionProfile provided");
ValueSetExpansionOutcome vse = expansionCache.getExpander().expand(vs, expProfile.setExcludeNested(!heirarchical));
}
ValueSetExpansionOutcome vse = expansionCache.getExpander()
.expand(vs, expProfile.setExcludeNested(!heirarchical));
if (vse.getValueset() != null) {
if (cache != null) {
FileOutputStream s = new FileOutputStream(cacheFn);
@ -324,19 +344,27 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return res;
}
} catch (NoTerminologyServiceException e) {
return new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.NOSERVICE);
return new ValueSetExpansionOutcome(
e.getMessage() == null ? e.getClass().getName() : e.getMessage(),
TerminologyServiceErrorClass.NOSERVICE);
} catch (Exception e) {
return new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
return new ValueSetExpansionOutcome(
e.getMessage() == null ? e.getClass().getName() : e.getMessage(),
TerminologyServiceErrorClass.UNKNOWN);
}
}
private ValueSetExpansionOutcome loadFromCache(ValueSet vs, String cacheFn) throws FileNotFoundException, Exception {
private ValueSetExpansionOutcome loadFromCache(ValueSet vs, String cacheFn)
throws FileNotFoundException, Exception {
JsonParser parser = new JsonParser();
Resource r = parser.parse(new FileInputStream(cacheFn));
if (r instanceof OperationOutcome)
return new ValueSetExpansionOutcome(((OperationOutcome) r).getIssue().get(0).getDetails().getText(), TerminologyServiceErrorClass.UNKNOWN);
else {
vs.setExpansion(((ValueSet) r).getExpansion()); // because what is cached might be from a different value set
if (r instanceof OperationOutcome) {
return new ValueSetExpansionOutcome(
((OperationOutcome) r).getIssue().get(0).getDetails().getText(),
TerminologyServiceErrorClass.UNKNOWN);
} else {
vs.setExpansion(((ValueSet) r)
.getExpansion()); // because what is cached might be from a different value set
return new ValueSetExpansionOutcome(vs);
}
}
@ -377,8 +405,9 @@ public abstract class BaseWorkerContext implements IWorkerContext {
csid.setVersion(cs.getVersion());
csid.setContent(cs.getContent());
csid.setHierarchyMeaning(CodeSystemHierarchyMeaning.GROUPEDBY);
for (ConceptDefinitionComponent cc : cs.getConcept())
for (ConceptDefinitionComponent cc : cs.getConcept()) {
csid.getConcept().add(processCSConcept(cc));
}
JsonParser parser = new JsonParser();
parser.setOutputStyle(OutputStyle.NORMAL);
ByteArrayOutputStream b = new ByteArrayOutputStream();
@ -392,16 +421,21 @@ public abstract class BaseWorkerContext implements IWorkerContext {
ConceptDefinitionComponent ccid = new ConceptDefinitionComponent();
ccid.setCode(cc.getCode());
ccid.setDisplay(cc.getDisplay());
for (ConceptDefinitionComponent cci : cc.getConcept())
for (ConceptDefinitionComponent cci : cc.getConcept()) {
ccid.getConcept().add(processCSConcept(cci));
}
return ccid;
}
public ValueSetExpansionOutcome expandOnServer(ValueSet vs, String fn) throws Exception {
if (noTerminologyServer)
return new ValueSetExpansionOutcome("Error expanding ValueSet: running without terminology services", TerminologyServiceErrorClass.NOSERVICE);
if (expProfile == null)
if (noTerminologyServer) {
return new ValueSetExpansionOutcome(
"Error expanding ValueSet: running without terminology services",
TerminologyServiceErrorClass.NOSERVICE);
}
if (expProfile == null) {
throw new Exception("No ExpansionProfile provided");
}
try {
Map<String, String> params = new HashMap<String, String>();
@ -411,32 +445,40 @@ public abstract class BaseWorkerContext implements IWorkerContext {
ValueSet result = txServer.expandValueset(vs, expProfile.setIncludeDefinition(false), params);
return new ValueSetExpansionOutcome(result);
} catch (Exception e) {
return new ValueSetExpansionOutcome("Error expanding ValueSet \""+vs.getUrl()+": "+e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
return new ValueSetExpansionOutcome(
"Error expanding ValueSet \"" + vs.getUrl() + ": " + e.getMessage(),
TerminologyServiceErrorClass.UNKNOWN);
}
}
private String getVSSummary(ValueSet vs) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (ConceptSetComponent cc : vs.getCompose().getInclude())
for (ConceptSetComponent cc : vs.getCompose().getInclude()) {
b.append("Include " + getIncSummary(cc));
for (ConceptSetComponent cc : vs.getCompose().getExclude())
}
for (ConceptSetComponent cc : vs.getCompose().getExclude()) {
b.append("Exclude " + getIncSummary(cc));
}
return b.toString();
}
private String getIncSummary(ConceptSetComponent cc) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (UriType vs : cc.getValueSet())
for (UriType vs : cc.getValueSet()) {
b.append(vs.asStringValue());
String vsd = b.length() > 0 ? " where the codes are in the value sets ("+b.toString()+")" : "";
}
String vsd =
b.length() > 0 ? " where the codes are in the value sets (" + b.toString() + ")" : "";
String system = cc.getSystem();
if (cc.hasConcept())
if (cc.hasConcept()) {
return Integer.toString(cc.getConcept().size()) + " codes from " + system + vsd;
}
if (cc.hasFilter()) {
String s = "";
for (ConceptSetFilterComponent f : cc.getFilter()) {
if (!Utilities.noString(s))
if (!Utilities.noString(s)) {
s = s + " & ";
}
s = s + f.getProperty() + " " + f.getOp().toCode() + " " + f.getValue();
}
return "from " + system + " where " + s + vsd;
@ -451,14 +493,18 @@ public abstract class BaseWorkerContext implements IWorkerContext {
cache = new HashMap<String, IWorkerContext.ValidationResult>();
validationCache.put(vs.getUrl(), cache);
}
if (cache.containsKey(cacheId))
if (cache.containsKey(cacheId)) {
return cache.get(cacheId);
if (!tryCache)
}
if (!tryCache) {
return null;
if (!cacheValidation)
}
if (!cacheValidation) {
return null;
if (failed.contains(vs.getUrl()))
}
if (failed.contains(vs.getUrl())) {
return null;
}
ValueSetExpansionOutcome vse = expandVS(vs, true, false);
if (vse.getValueset() == null || notcomplete(vse.getValueset())) {
failed.add(vs.getUrl());
@ -471,12 +517,17 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
private boolean notcomplete(ValueSet vs) {
if (!vs.hasExpansion())
if (!vs.hasExpansion()) {
return true;
if (!vs.getExpansion().getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-unclosed").isEmpty())
}
if (!vs.getExpansion()
.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-unclosed").isEmpty()) {
return true;
if (!vs.getExpansion().getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-toocostly").isEmpty())
}
if (!vs.getExpansion()
.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-toocostly").isEmpty()) {
return true;
}
return false;
}
@ -487,17 +538,23 @@ public abstract class BaseWorkerContext implements IWorkerContext {
cache = new HashMap<String, IWorkerContext.ValidationResult>();
validationCache.put(vs.getUrl(), cache);
}
if (cache.containsKey(cacheId))
if (cache.containsKey(cacheId)) {
return cache.get(cacheId);
}
if (validationCache.containsKey(vs.getUrl()) && validationCache.get(vs.getUrl()).containsKey(cacheId))
if (validationCache.containsKey(vs.getUrl()) && validationCache.get(vs.getUrl())
.containsKey(cacheId)) {
return validationCache.get(vs.getUrl()).get(cacheId);
if (!tryCache)
}
if (!tryCache) {
return null;
if (!cacheValidation)
}
if (!cacheValidation) {
return null;
if (failed.contains(vs.getUrl()))
}
if (failed.contains(vs.getUrl())) {
return null;
}
ValueSetExpansionOutcome vse = expandVS(vs, true, false);
if (vse.getValueset() == null || notcomplete(vse.getValueset())) {
failed.add(vs.getUrl());
@ -509,7 +566,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
private String cacheId(Coding coding) {
return "|"+coding.getSystem()+"|"+coding.getVersion()+"|"+coding.getCode()+"|"+coding.getDisplay();
return "|" + coding.getSystem() + "|" + coding.getVersion() + "|" + coding.getCode() + "|"
+ coding.getDisplay();
}
private String cacheId(CodeableConcept cc) {
@ -521,14 +579,17 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return b.toString();
}
private ValidationResult verifyCodeExternal(ValueSet vs, Coding coding, boolean tryCache) throws Exception {
private ValidationResult verifyCodeExternal(ValueSet vs, Coding coding, boolean tryCache)
throws Exception {
ValidationResult res = vs == null ? null : handleByCache(vs, coding, tryCache);
if (res != null)
if (res != null) {
return res;
}
Parameters pin = new Parameters();
pin.addParameter().setName("coding").setValue(coding);
if (vs != null)
if (vs != null) {
pin.addParameter().setName("valueSet").setResource(vs);
}
res = serverValidateCode(pin, vs == null);
if (vs != null) {
Map<String, ValidationResult> cache = validationCache.get(vs.getUrl());
@ -537,10 +598,12 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return res;
}
private ValidationResult verifyCodeExternal(ValueSet vs, CodeableConcept cc, boolean tryCache) throws Exception {
private ValidationResult verifyCodeExternal(ValueSet vs, CodeableConcept cc, boolean tryCache)
throws Exception {
ValidationResult res = handleByCache(vs, cc, tryCache);
if (res != null)
if (res != null) {
return res;
}
Parameters pin = new Parameters();
pin.addParameter().setName("codeableConcept").setValue(cc);
pin.addParameter().setName("valueSet").setResource(vs);
@ -551,18 +614,23 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
private ValidationResult serverValidateCode(Parameters pin, boolean doCache) throws Exception {
if (noTerminologyServer)
if (noTerminologyServer) {
return new ValidationResult(null, null, TerminologyServiceErrorClass.NOSERVICE);
}
String cacheName = doCache ? generateCacheName(pin) : null;
ValidationResult res = loadFromCache(cacheName);
if (res != null)
if (res != null) {
return res;
}
tlog("Terminology Server: $validate-code " + describeValidationParameters(pin));
for (ParametersParameterComponent pp : pin.getParameter())
if (pp.getName().equals("profile"))
for (ParametersParameterComponent pp : pin.getParameter()) {
if (pp.getName().equals("profile")) {
throw new Error("Can only specify profile in the context");
if (expProfile == null)
}
}
if (expProfile == null) {
throw new Exception("No ExpansionProfile provided");
}
pin.addParameter().setName("profile").setResource(expProfile);
Parameters pout = txServer.operateType(ValueSet.class, "validate-code", pin);
@ -571,29 +639,31 @@ public abstract class BaseWorkerContext implements IWorkerContext {
String display = null;
TerminologyServiceErrorClass err = TerminologyServiceErrorClass.UNKNOWN;
for (ParametersParameterComponent p : pout.getParameter()) {
if (p.getName().equals("result"))
if (p.getName().equals("result")) {
ok = ((BooleanType) p.getValue()).getValue().booleanValue();
else if (p.getName().equals("message"))
} else if (p.getName().equals("message")) {
message = ((StringType) p.getValue()).getValue();
else if (p.getName().equals("display"))
} else if (p.getName().equals("display")) {
display = ((StringType) p.getValue()).getValue();
else if (p.getName().equals("cause")) {
} else if (p.getName().equals("cause")) {
try {
IssueType it = IssueType.fromCode(((StringType) p.getValue()).getValue());
if (it == IssueType.UNKNOWN)
if (it == IssueType.UNKNOWN) {
err = TerminologyServiceErrorClass.UNKNOWN;
else if (it == IssueType.NOTSUPPORTED)
} else if (it == IssueType.NOTSUPPORTED) {
err = TerminologyServiceErrorClass.VALUESET_UNSUPPORTED;
}
} catch (FHIRException e) {
}
}
}
if (!ok)
if (!ok) {
res = new ValidationResult(IssueSeverity.ERROR, message, err);
else if (display != null)
} else if (display != null) {
res = new ValidationResult(new ConceptDefinitionComponent().setDisplay(display));
else
} else {
res = new ValidationResult(new ConceptDefinitionComponent());
}
saveToCache(res, cacheName);
return res;
}
@ -630,136 +700,169 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
private ValidationResult loadFromCache(String fn) throws FileNotFoundException, IOException {
if (fn == null)
if (fn == null) {
return null;
if (!(new File(fn).exists()))
}
if (!(new File(fn).exists())) {
return null;
}
String cnt = TextFile.fileToString(fn);
if (cnt.startsWith("!error: "))
if (cnt.startsWith("!error: ")) {
return new ValidationResult(IssueSeverity.ERROR, cnt.substring(8));
else if (cnt.startsWith("!warning: "))
} else if (cnt.startsWith("!warning: ")) {
return new ValidationResult(IssueSeverity.ERROR, cnt.substring(10));
else
} else {
return new ValidationResult(new ConceptDefinitionComponent().setDisplay(cnt));
}
}
private void saveToCache(ValidationResult res, String cacheName) throws IOException {
if (cacheName == null)
if (cacheName == null) {
return;
if (res.getDisplay() != null)
}
if (res.getDisplay() != null) {
TextFile.stringToFile(res.getDisplay(), cacheName);
else if (res.getMessage() != null) {
if (res.getSeverity() == IssueSeverity.WARNING)
} else if (res.getMessage() != null) {
if (res.getSeverity() == IssueSeverity.WARNING) {
TextFile.stringToFile("!warning: " + res.getMessage(), cacheName);
else
} else {
TextFile.stringToFile("!error: " + res.getMessage(), cacheName);
}
}
}
private String generateCacheName(Parameters pin) throws IOException {
if (cache == null)
if (cache == null) {
return null;
}
String json = new JsonParser().composeString(pin);
return Utilities.path(cache, "vc" + Integer.toString(json.hashCode()) + ".json");
}
@Override
public ValueSetExpansionComponent expandVS(ConceptSetComponent inc, boolean heirachical) throws TerminologyServiceException {
public ValueSetExpansionComponent expandVS(ConceptSetComponent inc, boolean heirachical)
throws TerminologyServiceException {
ValueSet vs = new ValueSet();
vs.setCompose(new ValueSetComposeComponent());
vs.getCompose().getInclude().add(inc);
ValueSetExpansionOutcome vse = expandVS(vs, true, heirachical);
ValueSet valueset = vse.getValueset();
if (valueset == null)
if (valueset == null) {
throw new TerminologyServiceException("Error Expanding ValueSet: " + vse.getError());
}
return valueset.getExpansion();
}
@Override
public ValidationResult validateCode(String system, String code, String display) {
try {
if (codeSystems.containsKey(system) && codeSystems.get(system) != null)
if (codeSystems.containsKey(system) && codeSystems.get(system) != null) {
return verifyCodeInCodeSystem(codeSystems.get(system), system, code, display);
else
return verifyCodeExternal(null, new Coding().setSystem(system).setCode(code).setDisplay(display), false);
} else {
return verifyCodeExternal(null,
new Coding().setSystem(system).setCode(code).setDisplay(display), false);
}
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code+"\" in system \""+system+"\": "+e.getMessage());
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code + "\" in system \"" + system + "\": " + e.getMessage());
}
}
@Override
public ValidationResult validateCode(Coding code, ValueSet vs) {
if (codeSystems.containsKey(code.getSystem()) && codeSystems.get(code.getSystem()) != null)
if (codeSystems.containsKey(code.getSystem()) && codeSystems.get(code.getSystem()) != null) {
try {
return verifyCodeInCodeSystem(codeSystems.get(code.getSystem()), code.getSystem(), code.getCode(), code.getDisplay());
return verifyCodeInCodeSystem(codeSystems.get(code.getSystem()), code.getSystem(),
code.getCode(), code.getDisplay());
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code+"\" in system \""+code.getSystem()+"\": "+e.getMessage());
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code + "\" in system \"" + code.getSystem() + "\": " + e
.getMessage());
}
else if (vs.hasExpansion())
} else if (vs.hasExpansion()) {
try {
return verifyCodeInternal(vs, code.getSystem(), code.getCode(), code.getDisplay());
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code+"\" in system \""+code.getSystem()+"\": "+e.getMessage());
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code + "\" in system \"" + code.getSystem() + "\": " + e
.getMessage());
}
else
} else {
try {
return verifyCodeExternal(vs, code, true);
} catch (Exception e) {
return new ValidationResult(IssueSeverity.WARNING, "Error validating code \""+code+"\" in system \""+code.getSystem()+"\": "+e.getMessage());
return new ValidationResult(IssueSeverity.WARNING,
"Error validating code \"" + code + "\" in system \"" + code.getSystem() + "\": " + e
.getMessage());
}
}
}
@Override
public ValidationResult validateCode(CodeableConcept code, ValueSet vs) {
try {
if (vs.hasExpansion())
if (vs.hasExpansion()) {
return verifyCodeInternal(vs, code);
else {
} else {
// we'll try expanding first; if that doesn't work, then we'll just pass it to the server to validate
// ... could be a problem if the server doesn't have the code systems we have locally, so we try not to depend on the server
try {
ValueSetExpansionOutcome vse = expandVS(vs, true, false);
if (vse.getValueset() != null && !hasTooCostlyExpansion(vse.getValueset()))
if (vse.getValueset() != null && !hasTooCostlyExpansion(vse.getValueset())) {
return verifyCodeInternal(vse.getValueset(), code);
}
} catch (Exception e) {
// failed? we'll just try the server
}
return verifyCodeExternal(vs, code, true);
}
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code.toString()+"\": "+e.getMessage(), TerminologyServiceErrorClass.SERVER_ERROR);
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code.toString() + "\": " + e.getMessage(),
TerminologyServiceErrorClass.SERVER_ERROR);
}
}
private boolean hasTooCostlyExpansion(ValueSet valueset) {
return valueset != null && valueset.hasExpansion() && ToolingExtensions.hasExtension(valueset.getExpansion(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly");
return valueset != null && valueset.hasExpansion() && ToolingExtensions
.hasExtension(valueset.getExpansion(),
"http://hl7.org/fhir/StructureDefinition/valueset-toocostly");
}
@Override
public ValidationResult validateCode(String system, String code, String display, ValueSet vs) {
try {
if (system == null && display == null)
if (system == null && display == null) {
return verifyCodeInternal(vs, code);
if ((codeSystems.containsKey(system) && codeSystems.get(system) != null) || vs.hasExpansion())
}
if ((codeSystems.containsKey(system) && codeSystems.get(system) != null) || vs
.hasExpansion()) {
return verifyCodeInternal(vs, system, code, display);
else
return verifyCodeExternal(vs, new Coding().setSystem(system).setCode(code).setDisplay(display), true);
} else {
return verifyCodeExternal(vs,
new Coding().setSystem(system).setCode(code).setDisplay(display), true);
}
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code+"\" in system \""+system+"\": "+e.getMessage(), TerminologyServiceErrorClass.SERVER_ERROR);
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code + "\" in system \"" + system + "\": " + e.getMessage(),
TerminologyServiceErrorClass.SERVER_ERROR);
}
}
@Override
public ValidationResult validateCode(String system, String code, String display, ConceptSetComponent vsi) {
public ValidationResult validateCode(String system, String code, String display,
ConceptSetComponent vsi) {
try {
ValueSet vs = new ValueSet();
vs.setUrl(Utilities.makeUuidUrn());
vs.getCompose().addInclude(vsi);
return verifyCodeExternal(vs, new Coding().setSystem(system).setCode(code).setDisplay(display), true);
return verifyCodeExternal(vs,
new Coding().setSystem(system).setCode(code).setDisplay(display), true);
} catch (Exception e) {
return new ValidationResult(IssueSeverity.FATAL, "Error validating code \""+code+"\" in system \""+system+"\": "+e.getMessage());
return new ValidationResult(IssueSeverity.FATAL,
"Error validating code \"" + code + "\" in system \"" + system + "\": " + e.getMessage());
}
}
@ -781,121 +884,159 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public List<ConceptMap> findMapsForSource(String url) {
List<ConceptMap> res = new ArrayList<ConceptMap>();
for (ConceptMap map : maps.values())
if (((Reference) map.getSource()).getReference().equals(url))
for (ConceptMap map : maps.values()) {
if (((Reference) map.getSource()).getReference().equals(url)) {
res.add(map);
}
}
return res;
}
private ValidationResult verifyCodeInternal(ValueSet vs, CodeableConcept code) throws Exception {
for (Coding c : code.getCoding()) {
ValidationResult res = verifyCodeInternal(vs, c.getSystem(), c.getCode(), c.getDisplay());
if (res.isOk())
if (res.isOk()) {
return res;
}
if (code.getCoding().isEmpty())
}
if (code.getCoding().isEmpty()) {
return new ValidationResult(IssueSeverity.ERROR, "None code provided");
else
return new ValidationResult(IssueSeverity.ERROR, "None of the codes are in the specified value set");
} else {
return new ValidationResult(IssueSeverity.ERROR,
"None of the codes are in the specified value set");
}
}
private ValidationResult verifyCodeInternal(ValueSet vs, String system, String code, String display) throws Exception {
if (vs.hasExpansion())
private ValidationResult verifyCodeInternal(ValueSet vs, String system, String code,
String display) throws Exception {
if (vs.hasExpansion()) {
return verifyCodeInExpansion(vs, system, code, display);
else {
} else {
ValueSetExpansionOutcome vse = expansionCache.getExpander().expand(vs, null);
if (vse.getValueset() != null)
return verifyCodeExternal(vs, new Coding().setSystem(system).setCode(code).setDisplay(display), false);
else
if (vse.getValueset() != null) {
return verifyCodeExternal(vs,
new Coding().setSystem(system).setCode(code).setDisplay(display), false);
} else {
return verifyCodeInExpansion(vse.getValueset(), system, code, display);
}
}
}
private ValidationResult verifyCodeInternal(ValueSet vs, String code) throws FileNotFoundException, ETooCostly, IOException, FHIRException {
if (vs.hasExpansion())
private ValidationResult verifyCodeInternal(ValueSet vs, String code)
throws FileNotFoundException, ETooCostly, IOException, FHIRException {
if (vs.hasExpansion()) {
return verifyCodeInExpansion(vs, code);
else {
} else {
ValueSetExpansionOutcome vse = expansionCache.getExpander().expand(vs, null);
if (vse.getValueset() == null)
if (vse.getValueset() == null) {
return new ValidationResult(IssueSeverity.ERROR, vse.getError(), vse.getErrorClass());
else
} else {
return verifyCodeInExpansion(vse.getValueset(), code);
}
}
}
private ValidationResult verifyCodeInCodeSystem(CodeSystem cs, String system, String code, String display) throws Exception {
private ValidationResult verifyCodeInCodeSystem(CodeSystem cs, String system, String code,
String display) throws Exception {
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), code);
if (cc == null)
if (cs.getContent().equals(CodeSystem.CodeSystemContentMode.COMPLETE))
return new ValidationResult(IssueSeverity.ERROR, "Unknown Code "+code+" in "+cs.getUrl());
else if (!cs.getContent().equals(CodeSystem.CodeSystemContentMode.NOTPRESENT))
return new ValidationResult(IssueSeverity.WARNING, "Unknown Code "+code+" in partial code list of "+cs.getUrl());
else
return verifyCodeExternal(null, new Coding().setSystem(system).setCode(code).setDisplay(display), false);
if (cc == null) {
if (cs.getContent().equals(CodeSystem.CodeSystemContentMode.COMPLETE)) {
return new ValidationResult(IssueSeverity.ERROR,
"Unknown Code " + code + " in " + cs.getUrl());
} else if (!cs.getContent().equals(CodeSystem.CodeSystemContentMode.NOTPRESENT)) {
return new ValidationResult(IssueSeverity.WARNING,
"Unknown Code " + code + " in partial code list of " + cs.getUrl());
} else {
return verifyCodeExternal(null,
new Coding().setSystem(system).setCode(code).setDisplay(display), false);
}
}
//
// return new ValidationResult(IssueSeverity.WARNING, "A definition was found for "+cs.getUrl()+", but it has no codes in the definition");
// return new ValidationResult(IssueSeverity.ERROR, "Unknown Code "+code+" in "+cs.getUrl());
if (display == null)
if (display == null) {
return new ValidationResult(cc);
}
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
if (cc.hasDisplay()) {
b.append(cc.getDisplay());
if (display.equalsIgnoreCase(cc.getDisplay()))
if (display.equalsIgnoreCase(cc.getDisplay())) {
return new ValidationResult(cc);
}
}
for (ConceptDefinitionDesignationComponent ds : cc.getDesignation()) {
b.append(ds.getValue());
if (display.equalsIgnoreCase(ds.getValue()))
if (display.equalsIgnoreCase(ds.getValue())) {
return new ValidationResult(cc);
}
return new ValidationResult(IssueSeverity.WARNING, "Display Name for "+code+" must be one of '"+b.toString()+"'", cc);
}
return new ValidationResult(IssueSeverity.WARNING,
"Display Name for " + code + " must be one of '" + b.toString() + "'", cc);
}
private ValidationResult verifyCodeInExpansion(ValueSet vs, String system,String code, String display) {
private ValidationResult verifyCodeInExpansion(ValueSet vs, String system, String code,
String display) {
ValueSetExpansionContainsComponent cc = findCode(vs.getExpansion().getContains(), code);
if (cc == null)
return new ValidationResult(IssueSeverity.ERROR, "Unknown Code "+code+" in "+vs.getUrl());
if (display == null)
return new ValidationResult(new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
if (cc == null) {
return new ValidationResult(IssueSeverity.ERROR,
"Unknown Code " + code + " in " + vs.getUrl());
}
if (display == null) {
return new ValidationResult(
new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
}
if (cc.hasDisplay()) {
if (display.equalsIgnoreCase(cc.getDisplay()))
return new ValidationResult(new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
return new ValidationResult(IssueSeverity.WARNING, "Display Name for "+code+" must be '"+cc.getDisplay()+"'", new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
if (display.equalsIgnoreCase(cc.getDisplay())) {
return new ValidationResult(
new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
}
return new ValidationResult(IssueSeverity.WARNING,
"Display Name for " + code + " must be '" + cc.getDisplay() + "'",
new ConceptDefinitionComponent().setCode(code).setDisplay(cc.getDisplay()));
}
return null;
}
private ValidationResult verifyCodeInExpansion(ValueSet vs, String code) throws FHIRException {
if (vs.getExpansion().hasExtension("http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
if (vs.getExpansion()
.hasExtension("http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
throw new FHIRException("Unable to validate core - value set is too costly to expand");
} else {
ValueSetExpansionContainsComponent cc = findCode(vs.getExpansion().getContains(), code);
if (cc == null)
return new ValidationResult(IssueSeverity.ERROR, "Unknown Code "+code+" in "+vs.getUrl());
if (cc == null) {
return new ValidationResult(IssueSeverity.ERROR,
"Unknown Code " + code + " in " + vs.getUrl());
}
return null;
}
}
private ValueSetExpansionContainsComponent findCode(List<ValueSetExpansionContainsComponent> contains, String code) {
private ValueSetExpansionContainsComponent findCode(
List<ValueSetExpansionContainsComponent> contains, String code) {
for (ValueSetExpansionContainsComponent cc : contains) {
if (code.equals(cc.getCode()))
if (code.equals(cc.getCode())) {
return cc;
}
ValueSetExpansionContainsComponent c = findCode(cc.getContains(), code);
if (c != null)
if (c != null) {
return c;
}
}
return null;
}
private ConceptDefinitionComponent findCodeInConcept(List<ConceptDefinitionComponent> concept, String code) {
private ConceptDefinitionComponent findCodeInConcept(List<ConceptDefinitionComponent> concept,
String code) {
for (ConceptDefinitionComponent cc : concept) {
if (code.equals(cc.getCode()))
if (code.equals(cc.getCode())) {
return cc;
}
ConceptDefinitionComponent c = findCodeInConcept(cc.getConcept(), code);
if (c != null)
if (c != null) {
return c;
}
}
return null;
}
@ -960,24 +1101,27 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
public void cacheResource(Resource r) throws Exception {
if (r instanceof ValueSet)
if (r instanceof ValueSet) {
seeValueSet(((ValueSet) r).getUrl(), (ValueSet) r);
else if (r instanceof CodeSystem)
} else if (r instanceof CodeSystem) {
seeCodeSystem(((CodeSystem) r).getUrl(), (CodeSystem) r);
else if (r instanceof StructureDefinition) {
} else if (r instanceof StructureDefinition) {
StructureDefinition sd = (StructureDefinition) r;
if ("http://hl7.org/fhir/StructureDefinition/Extension".equals(sd.getBaseDefinition()))
if ("http://hl7.org/fhir/StructureDefinition/Extension".equals(sd.getBaseDefinition())) {
seeExtensionDefinition(sd.getUrl(), sd);
else if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT)
} else if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) {
seeProfile(sd.getUrl(), sd);
}
}
}
public void dropResource(String type, String id) throws FHIRException {
if (type.equals("ValueSet"))
if (type.equals("ValueSet")) {
dropValueSet(id);
if (type.equals("CodeSystem"))
}
if (type.equals("CodeSystem")) {
dropCodeSystem(id);
}
if (type.equals("StructureDefinition")) {
dropProfile(id);
dropExtensionDefinition(id);
@ -994,7 +1138,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public StructureDefinition fetchTypeDefinition(String typeName) {
return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+typeName);
return fetchResource(StructureDefinition.class,
"http://hl7.org/fhir/StructureDefinition/" + typeName);
}
@Override
@ -1014,13 +1159,13 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
String message = theMessage;
if (Objects.nonNull(i18Nmessages) && i18Nmessages.containsKey(theMessage)) {
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
} else {
message = theMessage;
message = i18Nmessages.getString(theMessage);
}
}
return message;
}

View File

@ -1197,13 +1197,13 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
String message = theMessage;
if (Objects.nonNull(i18Nmessages) && i18Nmessages.containsKey(theMessage)) {
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
} else {
message = theMessage;
message = i18Nmessages.getString(theMessage);
}
}
return message;
}

View File

@ -1297,13 +1297,13 @@ public abstract class BaseWorkerContext implements IWorkerContext {
@Override
public String formatMessage(String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
String message = theMessage;
if (Objects.nonNull(i18Nmessages) && i18Nmessages.containsKey(theMessage)) {
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
} else {
message = theMessage;
message = i18Nmessages.getString(theMessage);
}
}
return message;
}