Update terminology server implementation and tests for changes to test cases

This commit is contained in:
Grahame Grieve 2023-07-21 05:38:09 +10:00
parent 93e1b3e4b3
commit cf1b53bba0
8 changed files with 143 additions and 102 deletions

View File

@ -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()) {

View File

@ -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

View File

@ -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);
}

View File

@ -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;
} }
} }

View File

@ -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);
} }

View File

@ -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";

View File

@ -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");
} }

View File

@ -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());
} }
} }