Update terminology server implementation and tests for changes to test cases
This commit is contained in:
parent
93e1b3e4b3
commit
cf1b53bba0
|
@ -483,9 +483,8 @@ public class CodeSystemUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasUse(ConceptPropertyComponent p, String use) {
|
private static boolean hasUse(ConceptPropertyComponent p, String use) {
|
||||||
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_METADATA)) {
|
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_USE)) {
|
||||||
Extension se = ext.getExtensionByUrl("use");
|
if (ext.hasValueCoding() && use.equals(ext.getValueCoding().getCode())) {
|
||||||
if (se != null && se.hasValueCoding() && use.equals(se.getValueCoding().getCode())) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -781,7 +780,7 @@ public class CodeSystemUtilities {
|
||||||
} else {
|
} else {
|
||||||
code = defineProperty(ret, p.getCode(), propertyTypeForType(p.getValue()));
|
code = defineProperty(ret, p.getCode(), propertyTypeForType(p.getValue()));
|
||||||
}
|
}
|
||||||
fdef.addProperty().setCode(code).setValue(p.getValue()).copyExtensions(p, "http://hl7.org/fhir/StructureDefinition/alternate-code-metadata");
|
fdef.addProperty().setCode(code).setValue(p.getValue()).copyExtensions(p, "http://hl7.org/fhir/StructureDefinition/alternate-code-use", "http://hl7.org/fhir/StructureDefinition/alternate-code-status");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ConceptDefinitionComponent t : fdef.getConcept()) {
|
for (ConceptDefinitionComponent t : fdef.getConcept()) {
|
||||||
|
|
|
@ -114,14 +114,15 @@ import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||||
|
import org.hl7.fhir.r5.terminologies.utilities.ValueSetProcessBase;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
|
|
||||||
public class ValueSetExpander {
|
public class ValueSetExpander extends ValueSetProcessBase {
|
||||||
|
|
||||||
|
|
||||||
private static final boolean REPORT_VERSION_ANYWAY = false;
|
private static final boolean REPORT_VERSION_ANYWAY = true;
|
||||||
|
|
||||||
private IWorkerContext context;
|
private IWorkerContext context;
|
||||||
private ValueSet focus;
|
private ValueSet focus;
|
||||||
|
@ -247,14 +248,14 @@ public class ValueSetExpander {
|
||||||
if (csProps != null && p.hasValue()) {
|
if (csProps != null && p.hasValue()) {
|
||||||
for (ConceptPropertyComponent cp : csProps) {
|
for (ConceptPropertyComponent cp : csProps) {
|
||||||
if (p.getValue().primitiveValue().equals(cp.getCode())) {
|
if (p.getValue().primitiveValue().equals(cp.getCode())) {
|
||||||
n.addProperty().setCode(cp.getCode()).setValue(cp.getValue()).copyExtensions(cp, "http://hl7.org/fhir/StructureDefinition/alternate-code-metadata");
|
n.addProperty().setCode(cp.getCode()).setValue(cp.getValue()).copyExtensions(cp, "http://hl7.org/fhir/StructureDefinition/alternate-code-use", "http://hl7.org/fhir/StructureDefinition/alternate-code-status");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (expProps != null && p.hasValue()) {
|
if (expProps != null && p.hasValue()) {
|
||||||
for (org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent cp : expProps) {
|
for (org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent cp : expProps) {
|
||||||
if (p.getValue().primitiveValue().equals(cp.getCode())) {
|
if (p.getValue().primitiveValue().equals(cp.getCode())) {
|
||||||
n.addProperty(cp).copyExtensions(cp, "http://hl7.org/fhir/StructureDefinition/alternate-code-metadata");
|
n.addProperty(cp).copyExtensions(cp, "http://hl7.org/fhir/StructureDefinition/alternate-code-use", "http://hl7.org/fhir/StructureDefinition/alternate-code-status");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,40 +328,15 @@ public class ValueSetExpander {
|
||||||
|
|
||||||
private List<String> getCodesForConcept(ValueSetExpansionContainsComponent focus, Parameters expParams) {
|
private List<String> getCodesForConcept(ValueSetExpansionContainsComponent focus, Parameters expParams) {
|
||||||
List<String> codes = new ArrayList<>();
|
List<String> codes = new ArrayList<>();
|
||||||
List<String> uses = new ArrayList<>();
|
|
||||||
codes.add(focus.getCode());
|
codes.add(focus.getCode());
|
||||||
boolean all = false;
|
|
||||||
for (ParametersParameterComponent p : expParams.getParameter()) {
|
|
||||||
if ("alternateCodes".equals(p.getName())) {
|
|
||||||
if (p.hasValueBooleanType()) {
|
|
||||||
all = p.getValueBooleanType().booleanValue();
|
|
||||||
} else if (p.getValue().isPrimitive()) {
|
|
||||||
String s = p.getValue().primitiveValue();
|
|
||||||
if (!Utilities.noString(s)) {
|
|
||||||
uses.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent p : focus.getProperty()) {
|
for (org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent p : focus.getProperty()) {
|
||||||
if ("alternateCode".equals(p.getCode()) && (all || hasUse(p, uses)) && p.getValue().isPrimitive()) {
|
if ("alternateCode".equals(p.getCode()) && (altCodeParams.passes(p.getExtension())) && p.getValue().isPrimitive()) {
|
||||||
codes.add(p.getValue().primitiveValue());
|
codes.add(p.getValue().primitiveValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasUse(org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent p, List<String> uses) {
|
|
||||||
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_METADATA)) {
|
|
||||||
Extension se = ext.getExtensionByUrl("use");
|
|
||||||
if (se != null && se.hasValueCoding() && Utilities.existsInList(se.getValueCoding().getCode(), uses)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private List<ConceptDefinitionDesignationComponent> convert(List<ConceptReferenceDesignationComponent> designations) {
|
private List<ConceptDefinitionDesignationComponent> convert(List<ConceptReferenceDesignationComponent> designations) {
|
||||||
List<ConceptDefinitionDesignationComponent> list = new ArrayList<ConceptDefinitionDesignationComponent>();
|
List<ConceptDefinitionDesignationComponent> list = new ArrayList<ConceptDefinitionDesignationComponent>();
|
||||||
for (ConceptReferenceDesignationComponent d : designations) {
|
for (ConceptReferenceDesignationComponent d : designations) {
|
||||||
|
@ -405,23 +381,9 @@ public class ValueSetExpander {
|
||||||
|
|
||||||
private List<String> getCodesForConcept(ConceptDefinitionComponent focus, Parameters expParams) {
|
private List<String> getCodesForConcept(ConceptDefinitionComponent focus, Parameters expParams) {
|
||||||
List<String> codes = new ArrayList<>();
|
List<String> codes = new ArrayList<>();
|
||||||
List<String> uses = new ArrayList<>();
|
|
||||||
codes.add(focus.getCode());
|
codes.add(focus.getCode());
|
||||||
boolean all = false;
|
|
||||||
for (ParametersParameterComponent p : expParams.getParameter()) {
|
|
||||||
if ("alternateCodes".equals(p.getName())) {
|
|
||||||
if (p.hasValueBooleanType()) {
|
|
||||||
all = p.getValueBooleanType().booleanValue();
|
|
||||||
} else if (p.getValue().isPrimitive()) {
|
|
||||||
String s = p.getValue().primitiveValue();
|
|
||||||
if (!Utilities.noString(s)) {
|
|
||||||
uses.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ConceptPropertyComponent p : focus.getProperty()) {
|
for (ConceptPropertyComponent p : focus.getProperty()) {
|
||||||
if ("alternateCode".equals(p.getCode()) && (all || hasUse(p, uses)) && p.getValue().isPrimitive()) {
|
if ("alternateCode".equals(p.getCode()) && (altCodeParams.passes(p.getExtension())) && p.getValue().isPrimitive()) {
|
||||||
codes.add(p.getValue().primitiveValue());
|
codes.add(p.getValue().primitiveValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,9 +391,8 @@ public class ValueSetExpander {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasUse(ConceptPropertyComponent p, List<String> uses) {
|
private static boolean hasUse(ConceptPropertyComponent p, List<String> uses) {
|
||||||
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_METADATA)) {
|
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_USE)) {
|
||||||
Extension se = ext.getExtensionByUrl("use");
|
if (ext.hasValueCoding() && Utilities.existsInList(ext.getValueCoding().getCode(), uses)) {
|
||||||
if (se != null && se.hasValueCoding() && Utilities.existsInList(se.getValueCoding().getCode(), uses)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -533,6 +494,9 @@ public class ValueSetExpander {
|
||||||
public ValueSetExpansionOutcome doExpand(ValueSet source, Parameters expParams) throws FHIRException, ETooCostly, FileNotFoundException, IOException, CodeSystemProviderExtension {
|
public ValueSetExpansionOutcome doExpand(ValueSet source, Parameters expParams) throws FHIRException, ETooCostly, FileNotFoundException, IOException, CodeSystemProviderExtension {
|
||||||
if (expParams == null)
|
if (expParams == null)
|
||||||
expParams = makeDefaultExpansion();
|
expParams = makeDefaultExpansion();
|
||||||
|
altCodeParams.seeParameters(expParams);
|
||||||
|
altCodeParams.seeValueSet(source);
|
||||||
|
|
||||||
source.checkNoModifiers("ValueSet", "expanding");
|
source.checkNoModifiers("ValueSet", "expanding");
|
||||||
focus = source.copy();
|
focus = source.copy();
|
||||||
focus.setIdBase(null);
|
focus.setIdBase(null);
|
||||||
|
@ -838,6 +802,13 @@ public class ValueSetExpander {
|
||||||
UriType u = new UriType(cs.getUrl() + (cs.hasVersion() ? "|"+cs.getVersion() : ""));
|
UriType u = new UriType(cs.getUrl() + (cs.hasVersion() ? "|"+cs.getVersion() : ""));
|
||||||
if (!existsInParams(exp.getParameter(), "version", u))
|
if (!existsInParams(exp.getParameter(), "version", u))
|
||||||
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(u));
|
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(u));
|
||||||
|
if (cs.hasUserData("supplements.installed")) {
|
||||||
|
for (String s : cs.getUserString("supplements.installed").split("\\,")) {
|
||||||
|
u = new UriType(s);
|
||||||
|
if (!existsInParams(exp.getParameter(), "version", u))
|
||||||
|
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(u));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||||
// special case - add all the code system
|
// special case - add all the code system
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package org.hl7.fhir.r5.terminologies.utilities;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
|
import org.hl7.fhir.r5.model.Parameters;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.model.BooleanType;
|
||||||
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||||
|
import org.hl7.fhir.r5.model.DataType;
|
||||||
|
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||||
|
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||||
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
|
||||||
|
public class ValueSetProcessBase {
|
||||||
|
|
||||||
|
public static class AlternateCodesProcessingRules {
|
||||||
|
private boolean all;
|
||||||
|
private List<String> uses = new ArrayList<>();
|
||||||
|
|
||||||
|
public AlternateCodesProcessingRules(boolean b) {
|
||||||
|
all = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void seeParameter(DataType value) {
|
||||||
|
if (value != null) {
|
||||||
|
if (value instanceof BooleanType) {
|
||||||
|
all = ((BooleanType) value).booleanValue();
|
||||||
|
uses.clear();
|
||||||
|
} else if (value.isPrimitive()) {
|
||||||
|
String s = value.primitiveValue();
|
||||||
|
if (!Utilities.noString(s)) {
|
||||||
|
uses.add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seeParameters(Parameters pp) {
|
||||||
|
for (ParametersParameterComponent p : pp.getParameter()) {
|
||||||
|
String name = p.getName();
|
||||||
|
if ("includeAlternateCodes".equals(name)) {
|
||||||
|
DataType value = p.getValue();
|
||||||
|
seeParameter(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seeValueSet(ValueSet vs) {
|
||||||
|
for (Extension ext : vs.getCompose().getExtension()) {
|
||||||
|
if ("http://hl7.org/fhir/tools/StructureDefinion/valueset-expansion-param".equals(ext.getUrl())) {
|
||||||
|
String name = ext.getExtensionString("name");
|
||||||
|
Extension value = ext.getExtensionByUrl("value");
|
||||||
|
if ("includeAlternateCodes".equals(name) && value != null && value.hasValue()) {
|
||||||
|
seeParameter(value.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean passes(List<Extension> extensions) {
|
||||||
|
if (all) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Extension ext : extensions) {
|
||||||
|
if (ToolingExtensions.EXT_CS_ALTERNATE_USE.equals(ext.getUrl())) {
|
||||||
|
if (ext.hasValueCoding() && Utilities.existsInList(ext.getValueCoding().getCode(), uses)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AlternateCodesProcessingRules altCodeParams = new AlternateCodesProcessingRules(false);
|
||||||
|
protected AlternateCodesProcessingRules allAltCodes = new AlternateCodesProcessingRules(true);
|
||||||
|
}
|
|
@ -80,6 +80,7 @@ import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||||
import org.hl7.fhir.r5.terminologies.providers.SpecialCodeSystem;
|
import org.hl7.fhir.r5.terminologies.providers.SpecialCodeSystem;
|
||||||
import org.hl7.fhir.r5.terminologies.providers.URICodeSystem;
|
import org.hl7.fhir.r5.terminologies.providers.URICodeSystem;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||||
|
import org.hl7.fhir.r5.terminologies.utilities.ValueSetProcessBase;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
||||||
|
@ -93,7 +94,7 @@ import org.hl7.fhir.utilities.validation.ValidationOptions.ValueSetMode;
|
||||||
|
|
||||||
import com.google.j2objc.annotations.ReflectionSupport.Level;
|
import com.google.j2objc.annotations.ReflectionSupport.Level;
|
||||||
|
|
||||||
public class ValueSetValidator {
|
public class ValueSetValidator extends ValueSetProcessBase {
|
||||||
|
|
||||||
private ValueSet valueset;
|
private ValueSet valueset;
|
||||||
private IWorkerContext context;
|
private IWorkerContext context;
|
||||||
|
@ -112,6 +113,7 @@ public class ValueSetValidator {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.expansionProfile = expansionProfile;
|
this.expansionProfile = expansionProfile;
|
||||||
this.txCaps = txCaps;
|
this.txCaps = txCaps;
|
||||||
|
analyseValueSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueSetValidator(ValidationOptions options, ValueSet source, IWorkerContext context, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
public ValueSetValidator(ValidationOptions options, ValueSet source, IWorkerContext context, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||||
|
@ -142,6 +144,8 @@ public class ValueSetValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyseValueSet() {
|
private void analyseValueSet() {
|
||||||
|
altCodeParams.seeParameters(expansionProfile);
|
||||||
|
altCodeParams.seeValueSet(valueset);
|
||||||
if (localContext != null) {
|
if (localContext != null) {
|
||||||
if (valueset != null) {
|
if (valueset != null) {
|
||||||
for (ConceptSetComponent i : valueset.getCompose().getInclude()) {
|
for (ConceptSetComponent i : valueset.getCompose().getInclude()) {
|
||||||
|
@ -651,7 +655,7 @@ public class ValueSetValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValidationResult validateCode(String path, Coding code, CodeSystem cs, CodeableConcept vcc) {
|
private ValidationResult validateCode(String path, Coding code, CodeSystem cs, CodeableConcept vcc) {
|
||||||
ConceptDefinitionComponent cc = cs.hasUserData("tx.cs.special") ? ((SpecialCodeSystem) cs.getUserData("tx.cs.special")).findConcept(code) : findCodeInConcept(cs.getConcept(), code.getCode(), true);
|
ConceptDefinitionComponent cc = cs.hasUserData("tx.cs.special") ? ((SpecialCodeSystem) cs.getUserData("tx.cs.special")).findConcept(code) : findCodeInConcept(cs.getConcept(), code.getCode(), allAltCodes);
|
||||||
if (cc == null) {
|
if (cc == null) {
|
||||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||||
String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_FRAGMENT, code.getCode(), cs.getUrl());
|
String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_FRAGMENT, code.getCode(), cs.getUrl());
|
||||||
|
@ -815,18 +819,18 @@ public class ValueSetValidator {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConceptDefinitionComponent findCodeInConcept(ConceptDefinitionComponent concept, String code, boolean allAlternates) {
|
private ConceptDefinitionComponent findCodeInConcept(ConceptDefinitionComponent concept, String code, AlternateCodesProcessingRules altCodeRules) {
|
||||||
if (code.equals(concept.getCode())) {
|
if (code.equals(concept.getCode())) {
|
||||||
return concept;
|
return concept;
|
||||||
}
|
}
|
||||||
ConceptDefinitionComponent cc = findCodeInConcept(concept.getConcept(), code, allAlternates);
|
ConceptDefinitionComponent cc = findCodeInConcept(concept.getConcept(), code, altCodeRules);
|
||||||
if (cc != null) {
|
if (cc != null) {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
if (concept.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
if (concept.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) concept.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) concept.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||||
for (ConceptDefinitionComponent c : children) {
|
for (ConceptDefinitionComponent c : children) {
|
||||||
cc = findCodeInConcept(c, code, allAlternates);
|
cc = findCodeInConcept(c, code, altCodeRules);
|
||||||
if (cc != null) {
|
if (cc != null) {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
@ -835,15 +839,15 @@ public class ValueSetValidator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConceptDefinitionComponent findCodeInConcept(List<ConceptDefinitionComponent> concept, String code, boolean allAlternates) {
|
private ConceptDefinitionComponent findCodeInConcept(List<ConceptDefinitionComponent> concept, String code, AlternateCodesProcessingRules altCodeRules) {
|
||||||
for (ConceptDefinitionComponent cc : concept) {
|
for (ConceptDefinitionComponent cc : concept) {
|
||||||
if (code.equals(cc.getCode())) {
|
if (code.equals(cc.getCode())) {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
if (Utilities.existsInList(code, alternateCodes(cc, allAlternates))) {
|
if (Utilities.existsInList(code, alternateCodes(cc, altCodeRules))) {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
ConceptDefinitionComponent c = findCodeInConcept(cc, code, allAlternates);
|
ConceptDefinitionComponent c = findCodeInConcept(cc, code, altCodeRules);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -852,40 +856,16 @@ public class ValueSetValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> alternateCodes(ConceptDefinitionComponent focus, boolean allAlternates) {
|
private List<String> alternateCodes(ConceptDefinitionComponent focus, AlternateCodesProcessingRules altCodeRules) {
|
||||||
List<String> codes = new ArrayList<>();
|
List<String> codes = new ArrayList<>();
|
||||||
List<String> uses = new ArrayList<>();
|
|
||||||
boolean all = false;
|
|
||||||
for (ParametersParameterComponent p : expansionProfile.getParameter()) {
|
|
||||||
if ("alternateCodes".equals(p.getName())) {
|
|
||||||
if (p.hasValueBooleanType()) {
|
|
||||||
all = p.getValueBooleanType().booleanValue();
|
|
||||||
} else if (p.getValue().isPrimitive()) {
|
|
||||||
String s = p.getValue().primitiveValue();
|
|
||||||
if (!Utilities.noString(s)) {
|
|
||||||
uses.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ConceptPropertyComponent p : focus.getProperty()) {
|
for (ConceptPropertyComponent p : focus.getProperty()) {
|
||||||
if ("alternateCode".equals(p.getCode()) && (allAlternates || all || hasUse(p, uses)) && p.getValue().isPrimitive()) {
|
if ("alternateCode".equals(p.getCode()) && (altCodeRules.passes(p.getExtension())) && p.getValue().isPrimitive()) {
|
||||||
codes.add(p.getValue().primitiveValue());
|
codes.add(p.getValue().primitiveValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasUse(ConceptPropertyComponent p, List<String> uses) {
|
|
||||||
for (Extension ext : p.getExtensionsByUrl(ToolingExtensions.EXT_CS_ALTERNATE_METADATA)) {
|
|
||||||
Extension se = ext.getExtensionByUrl("use");
|
|
||||||
if (se != null && se.hasValueCoding() && Utilities.existsInList(se.getValueCoding().getCode(), uses)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String systemForCodeInValueSet(String code, List<String> problems) {
|
private String systemForCodeInValueSet(String code, List<String> problems) {
|
||||||
Set<String> sys = new HashSet<>();
|
Set<String> sys = new HashSet<>();
|
||||||
|
@ -945,7 +925,7 @@ public class ValueSetValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), code, true);
|
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), code, allAltCodes);
|
||||||
if (cc != null) {
|
if (cc != null) {
|
||||||
sys.add(vsi.getSystem());
|
sys.add(vsi.getSystem());
|
||||||
}
|
}
|
||||||
|
@ -1127,7 +1107,7 @@ public class ValueSetValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ConceptDefinitionComponent> list = cs.getConcept();
|
List<ConceptDefinitionComponent> list = cs.getConcept();
|
||||||
ok = validateCodeInConceptList(code, cs, list, true);
|
ok = validateCodeInConceptList(code, cs, list, allAltCodes);
|
||||||
if (ok && vsi.hasConcept()) {
|
if (ok && vsi.hasConcept()) {
|
||||||
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
||||||
if (cc.getCode().equals(code)) {
|
if (cc.getCode().equals(code)) {
|
||||||
|
@ -1137,7 +1117,7 @@ public class ValueSetValidator {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// recheck that this is a valid alternate code
|
// recheck that this is a valid alternate code
|
||||||
ok = validateCodeInConceptList(code, cs, list, false);
|
ok = validateCodeInConceptList(code, cs, list, altCodeParams);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1206,24 +1186,24 @@ public class ValueSetValidator {
|
||||||
if (!excludeRoot && code.equals(f.getValue())) {
|
if (!excludeRoot && code.equals(f.getValue())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), f.getValue(), false);
|
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), f.getValue(), altCodeParams);
|
||||||
if (cc == null) {
|
if (cc == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ConceptDefinitionComponent cc2 = findCodeInConcept(cc, code, false);
|
ConceptDefinitionComponent cc2 = findCodeInConcept(cc, code, altCodeParams);
|
||||||
return cc2 != null && cc2 != cc;
|
return cc2 != null && cc2 != cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateCodeInConceptList(String code, CodeSystem def, List<ConceptDefinitionComponent> list, boolean allAlternates) {
|
public boolean validateCodeInConceptList(String code, CodeSystem def, List<ConceptDefinitionComponent> list, AlternateCodesProcessingRules altCodeRules) {
|
||||||
if (def.getCaseSensitive()) {
|
if (def.getCaseSensitive()) {
|
||||||
for (ConceptDefinitionComponent cc : list) {
|
for (ConceptDefinitionComponent cc : list) {
|
||||||
if (cc.getCode().equals(code)) {
|
if (cc.getCode().equals(code)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Utilities.existsInList(code, alternateCodes(cc, allAlternates))) {
|
if (Utilities.existsInList(code, alternateCodes(cc, altCodeRules))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cc.hasConcept() && validateCodeInConceptList(code, def, cc.getConcept(), allAlternates)) {
|
if (cc.hasConcept() && validateCodeInConceptList(code, def, cc.getConcept(), altCodeRules)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1212,7 @@ public class ValueSetValidator {
|
||||||
if (cc.getCode().equalsIgnoreCase(code)) {
|
if (cc.getCode().equalsIgnoreCase(code)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cc.hasConcept() && validateCodeInConceptList(code, def, cc.getConcept(), allAlternates)) {
|
if (cc.hasConcept() && validateCodeInConceptList(code, def, cc.getConcept(), altCodeRules)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,8 +351,16 @@ public class CompareUtilities extends BaseTestingUtilities {
|
||||||
private static boolean matches(String actualJsonString, String expectedJsonString) {
|
private static boolean matches(String actualJsonString, String expectedJsonString) {
|
||||||
if (expectedJsonString.startsWith("$") && expectedJsonString.endsWith("$")) {
|
if (expectedJsonString.startsWith("$") && expectedJsonString.endsWith("$")) {
|
||||||
if (expectedJsonString.startsWith("$choice:")) {
|
if (expectedJsonString.startsWith("$choice:")) {
|
||||||
return Utilities.existsInList(actualJsonString, readChoices(expectedJsonString));
|
return Utilities.existsInList(actualJsonString, readChoices(8, expectedJsonString));
|
||||||
|
|
||||||
|
} else if (expectedJsonString.startsWith("$fragments:")) {
|
||||||
|
List<String> fragments = readChoices(11, expectedJsonString);
|
||||||
|
for (String f : fragments) {
|
||||||
|
if (!actualJsonString.toLowerCase().contains(f.toLowerCase())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
switch (expectedJsonString) {
|
switch (expectedJsonString) {
|
||||||
case "$$" : return true;
|
case "$$" : return true;
|
||||||
|
@ -367,9 +375,9 @@ public class CompareUtilities extends BaseTestingUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> readChoices(String s) {
|
private static List<String> readChoices(int offset, String s) {
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
s = s.substring(8, s.length()-1);
|
s = s.substring(offset, s.length()-1);
|
||||||
for (String p : s.split("\\|")) {
|
for (String p : s.split("\\|")) {
|
||||||
list.add(p);
|
list.add(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,8 @@ public class ToolingExtensions {
|
||||||
public static final String EXT_EXTENSION_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style";
|
public static final String EXT_EXTENSION_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style";
|
||||||
public static final String EXT_LOGICAL_TARGET = "http://hl7.org/fhir/tools/StructureDefinition/logical-target";
|
public static final String EXT_LOGICAL_TARGET = "http://hl7.org/fhir/tools/StructureDefinition/logical-target";
|
||||||
public static final String EXT_PROFILE_MAPPING = "http://hl7.org/fhir/tools/StructureDefinition/profile-mapping";
|
public static final String EXT_PROFILE_MAPPING = "http://hl7.org/fhir/tools/StructureDefinition/profile-mapping";
|
||||||
public static final String EXT_CS_ALTERNATE_METADATA = "http://hl7.org/fhir/StructureDefinition/alternate-code-metadata";
|
public static final String EXT_CS_ALTERNATE_USE = "http://hl7.org/fhir/StructureDefinition/alternate-code-use";
|
||||||
|
public static final String EXT_CS_ALTERNATE_STATUS = "http://hl7.org/fhir/StructureDefinition/alternate-code-status";
|
||||||
|
|
||||||
// validated
|
// validated
|
||||||
// private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
|
// private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
|
||||||
|
|
|
@ -47,7 +47,8 @@ public class TxTesterScrubbers {
|
||||||
"http://hl7.org/fhir/test/ValueSet/extensions-bad-supplement",
|
"http://hl7.org/fhir/test/ValueSet/extensions-bad-supplement",
|
||||||
"http://hl7.org/fhir/test/ValueSet/simple-all",
|
"http://hl7.org/fhir/test/ValueSet/simple-all",
|
||||||
"http://hl7.org/fhir/test/ValueSet/simple-enumerated",
|
"http://hl7.org/fhir/test/ValueSet/simple-enumerated",
|
||||||
"http://hl7.org/fhir/StructureDefinition/alternate-code-metadata",
|
"http://hl7.org/fhir/StructureDefinition/alternate-code-use",
|
||||||
|
"http://hl7.org/fhir/StructureDefinition/alternate-code-status",
|
||||||
"http://hl7.org/fhir/test/ValueSet/simple-filter-isa");
|
"http://hl7.org/fhir/test/ValueSet/simple-filter-isa");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ public class TerminologyServiceTests {
|
||||||
}
|
}
|
||||||
ValidationEngine engine = new ValidationEngine(this.baseEngine);
|
ValidationEngine engine = new ValidationEngine(this.baseEngine);
|
||||||
for (String s : setup.suite.forceArray("setup").asStrings()) {
|
for (String s : setup.suite.forceArray("setup").asStrings()) {
|
||||||
|
// System.out.println(s);
|
||||||
Resource res = loadResource(s);
|
Resource res = loadResource(s);
|
||||||
engine.seeResource(res);
|
engine.seeResource(res);
|
||||||
}
|
}
|
||||||
|
@ -245,9 +246,9 @@ public class TerminologyServiceTests {
|
||||||
if (p.hasParameter("mode") && "lenient-display-validation".equals(p.getParameterString("mode"))) {
|
if (p.hasParameter("mode") && "lenient-display-validation".equals(p.getParameterString("mode"))) {
|
||||||
options = options.setDisplayWarningMode(true);
|
options = options.setDisplayWarningMode(true);
|
||||||
}
|
}
|
||||||
engine.getContext().getExpansionParameters().clearParameters("alternateCodes");
|
engine.getContext().getExpansionParameters().clearParameters("includeAlternateCodes");
|
||||||
for (ParametersParameterComponent pp : p.getParameter()) {
|
for (ParametersParameterComponent pp : p.getParameter()) {
|
||||||
if ("alternateCodes".equals(pp.getName())) {
|
if ("includeAlternateCodes".equals(pp.getName())) {
|
||||||
engine.getContext().getExpansionParameters().addParameter(pp.copy());
|
engine.getContext().getExpansionParameters().addParameter(pp.copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue