Merge pull request #1379 from hapifhir/2023-08-gg-terminology-status
warnings for status on terminology resources
This commit is contained in:
commit
83bbd09627
|
@ -2,8 +2,11 @@
|
|||
|
||||
* Fix invalid integer detection
|
||||
* Improved invariant checking
|
||||
* Create warnings for status on terminology resources
|
||||
|
||||
## Other code changes
|
||||
|
||||
* Update obligation handling code for split definitions
|
||||
* Update ICF importer to handle grouping levels
|
||||
* fix up copy directory for case differences
|
||||
|
||||
|
|
|
@ -1490,6 +1490,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
String system = null;
|
||||
String code = null;
|
||||
String version = null;
|
||||
List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
|
||||
TerminologyServiceErrorClass err = TerminologyServiceErrorClass.UNKNOWN;
|
||||
for (ParametersParameterComponent p : pOut.getParameter()) {
|
||||
if (p.hasValue()) {
|
||||
|
@ -1506,7 +1508,19 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
} else if (p.getName().equals("code")) {
|
||||
code = ((PrimitiveType<?>) p.getValue()).asStringValue();
|
||||
} else if (p.getName().equals("x-caused-by-unknown-system")) {
|
||||
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
|
||||
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
|
||||
} else if (p.getName().equals("warning-withdrawn")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
iss.getDetails().setText(formatMessage(I18nConstants.MSG_WITHDRAWN, ((PrimitiveType<?>) p.getValue()).asStringValue()));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("warning-deprecated")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
iss.getDetails().setText(formatMessage(I18nConstants.MSG_DEPRECATED, ((PrimitiveType<?>) p.getValue()).asStringValue()));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("warning-retired")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
iss.getDetails().setText(formatMessage(I18nConstants.MSG_RETIRED, ((PrimitiveType<?>) p.getValue()).asStringValue()));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("cause")) {
|
||||
try {
|
||||
IssueType it = IssueType.fromCode(((StringType) p.getValue()).getValue());
|
||||
|
@ -1524,15 +1538,18 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
}
|
||||
ValidationResult res = null;
|
||||
if (!ok) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, message+" (from "+tcc.getClient().getId()+")", err, null).setTxLink(txLog.getLastId());
|
||||
res = new ValidationResult(IssueSeverity.ERROR, message+" (from "+tcc.getClient().getId()+")", err, null).setTxLink(txLog.getLastId());
|
||||
} else if (message != null && !message.equals("No Message returned")) {
|
||||
return new ValidationResult(IssueSeverity.WARNING, message+" (from "+tcc.getClient().getId()+")", system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display, null).setTxLink(txLog.getLastId());
|
||||
res = new ValidationResult(IssueSeverity.WARNING, message+" (from "+tcc.getClient().getId()+")", system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display, null).setTxLink(txLog.getLastId());
|
||||
} else if (display != null) {
|
||||
return new ValidationResult(system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display).setTxLink(txLog.getLastId());
|
||||
res = new ValidationResult(system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display).setTxLink(txLog.getLastId());
|
||||
} else {
|
||||
return new ValidationResult(system, version, new ConceptDefinitionComponent().setCode(code), null).setTxLink(txLog.getLastId());
|
||||
res = new ValidationResult(system, version, new ConceptDefinitionComponent().setCode(code), null).setTxLink(txLog.getLastId());
|
||||
}
|
||||
res.setIssues(issues );
|
||||
return res;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -124,7 +124,7 @@ public interface IWorkerContext {
|
|||
private List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
private CodeableConcept codeableConcept;
|
||||
private Set<String> unknownSystems;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass="
|
||||
|
@ -315,6 +315,14 @@ public interface IWorkerContext {
|
|||
}
|
||||
}
|
||||
|
||||
public void setIssues(List<OperationOutcomeIssueComponent> issues) {
|
||||
if (this.issues != null) {
|
||||
issues.addAll(this.issues);
|
||||
}
|
||||
this.issues = issues;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CodingValidationRequest {
|
||||
|
|
|
@ -1753,6 +1753,14 @@ public String toString() {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasParameterValue(String name, String value) {
|
||||
for (ParametersParameterComponent p : getParameter()) {
|
||||
if (p.getName().equals(name) && p.hasValue() && value.equals(p.getValue().primitiveValue()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasParameter(String name) {
|
||||
|
|
|
@ -2839,12 +2839,24 @@ public class ValueSet extends MetadataResource {
|
|||
, total, offset, parameter, property, contains);
|
||||
}
|
||||
|
||||
public String fhirType() {
|
||||
return "ValueSet.expansion";
|
||||
public boolean hasParameterValue(String name, String value) {
|
||||
for (ValueSetExpansionParameterComponent p : getParameter()) {
|
||||
if (name.equals(p.getName()) && p.hasValue() && value.equals(p.getValue().primitiveValue())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
public void addParameter(String name, DataType value) {
|
||||
getParameter().add(new ValueSetExpansionParameterComponent(name).setValue(value));
|
||||
}
|
||||
|
||||
public String fhirType() {
|
||||
return "ValueSet.expansion";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Block()
|
||||
public static class ValueSetExpansionParameterComponent extends BackboneElement implements IBaseBackboneElement {
|
||||
|
|
|
@ -124,7 +124,6 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private static final boolean REPORT_VERSION_ANYWAY = true;
|
||||
|
||||
private IWorkerContext context;
|
||||
private ValueSet focus;
|
||||
private List<String> allErrors = new ArrayList<>();
|
||||
private List<String> requiredSupplements = new ArrayList<>();
|
||||
|
@ -151,9 +150,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private ValueSetExpansionContainsComponent addCode(WorkingContext wc, String system, String code, String display, String dispLang, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
||||
boolean isAbstract, boolean inactive, String definition, List<ValueSet> filters, boolean noInactive, boolean deprecated, List<ValueSetExpansionPropertyComponent> vsProp,
|
||||
List<ConceptPropertyComponent> csProps, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList) throws ETooCostly {
|
||||
List<ConceptPropertyComponent> csProps, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList, ValueSetExpansionComponent exp) throws ETooCostly {
|
||||
|
||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code, exp))
|
||||
return null;
|
||||
if (noInactive && inactive) {
|
||||
return null;
|
||||
|
@ -285,10 +284,12 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
return n;
|
||||
}
|
||||
|
||||
private boolean filterContainsCode(List<ValueSet> filters, String system, String code) {
|
||||
for (ValueSet vse : filters)
|
||||
private boolean filterContainsCode(List<ValueSet> filters, String system, String code, ValueSetExpansionComponent exp) {
|
||||
for (ValueSet vse : filters) {
|
||||
checkCanonical(exp, vse);
|
||||
if (expansionContainsCode(vse.getExpansion().getContains(), system, code))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -312,18 +313,18 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws FHIRException, ETooCostly {
|
||||
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
focus.checkNoModifiers("Expansion.contains", "expanding");
|
||||
ValueSetExpansionContainsComponent np = null;
|
||||
for (String code : getCodesForConcept(focus, expParams)) {
|
||||
ValueSetExpansionContainsComponent t = addCode(wc, focus.getSystem(), code, focus.getDisplay(), vsSrc.getLanguage(), parent,
|
||||
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), focus.getExtensionString(ToolingExtensions.EXT_DEFINITION), filters, noInactive, false, vsProps, null, focus.getProperty(), null, focus.getExtension());
|
||||
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), focus.getExtensionString(ToolingExtensions.EXT_DEFINITION), filters, noInactive, false, vsProps, null, focus.getProperty(), null, focus.getExtension(), exp);
|
||||
if (np == null) {
|
||||
np = t;
|
||||
}
|
||||
}
|
||||
for (ValueSetExpansionContainsComponent c : focus.getContains())
|
||||
addCodeAndDescendents(wc, c, np, expParams, filters, noInactive, vsProps, vsSrc);
|
||||
addCodeAndDescendents(wc, c, np, expParams, filters, noInactive, vsProps, vsSrc, exp);
|
||||
}
|
||||
|
||||
private List<String> getCodesForConcept(ValueSetExpansionContainsComponent focus, Parameters expParams) {
|
||||
|
@ -349,8 +350,8 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
return list;
|
||||
}
|
||||
|
||||
private void addCodeAndDescendents(WorkingContext wc,CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, ConceptFilter filterFunc, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, List<WorkingContext> otherFilters) throws FHIRException, ETooCostly {
|
||||
private void addCodeAndDescendents(WorkingContext wc, CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, ConceptFilter filterFunc, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, List<WorkingContext> otherFilters, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
def.checkNoModifiers("Code in Code System", "expanding");
|
||||
if (exclusion != null) {
|
||||
if (exclusion.getCode().equals(def.getCode()))
|
||||
|
@ -362,19 +363,19 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
boolean dep = CodeSystemUtilities.isDeprecated(cs, def, false);
|
||||
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def) && passesOtherFilters(otherFilters, cs, def.getCode())) {
|
||||
for (String code : getCodesForConcept(def, expParams)) {
|
||||
ValueSetExpansionContainsComponent t = addCode(wc, system, code, def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, def.getDefinition(), filters, noInactive, dep, vsProps, def.getProperty(), null, def.getExtension(), null);
|
||||
ValueSetExpansionContainsComponent t = addCode(wc, system, code, def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, def.getDefinition(), filters, noInactive, dep, vsProps, def.getProperty(), null, def.getExtension(), null, exp);
|
||||
if (np == null) {
|
||||
np = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ConceptDefinitionComponent c : def.getConcept()) {
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters);
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters, exp);
|
||||
}
|
||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||
for (ConceptDefinitionComponent c : children)
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters);
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters, exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,7 +402,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
|
||||
|
||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws ETooCostly, FHIRException {
|
||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws ETooCostly, FHIRException {
|
||||
if (expand != null) {
|
||||
if (expand.getContains().size() > maxExpansionSize)
|
||||
throw failCostly(context.formatMessage(I18nConstants.VALUESET_TOO_COSTLY, vsSrc.getUrl(), ">" + Integer.toString(expand.getContains().size())));
|
||||
|
@ -410,7 +411,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
params.add(p);
|
||||
}
|
||||
|
||||
copyImportContains(expand.getContains(), null, expParams, filters, noInactive, vsProps, vsSrc);
|
||||
copyImportContains(expand.getContains(), null, expParams, filters, noInactive, vsProps, vsSrc, exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,8 +451,6 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
throw fail("not done yet - multiple filters");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void excludeCodes(WorkingContext wc, ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(wc, c.getSystem(), c.getCode());
|
||||
|
@ -460,8 +459,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private boolean existsInParams(List<ValueSetExpansionParameterComponent> params, String name, DataType value) {
|
||||
for (ValueSetExpansionParameterComponent p : params) {
|
||||
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false))
|
||||
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -503,6 +503,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
focus.setExpansion(new ValueSet.ValueSetExpansionComponent());
|
||||
focus.getExpansion().setTimestampElement(DateTimeType.now());
|
||||
focus.getExpansion().setIdentifier(Factory.createUUID());
|
||||
checkCanonical(focus.getExpansion(), focus);
|
||||
for (ParametersParameterComponent p : expParams.getParameter()) {
|
||||
if (Utilities.existsInList(p.getName(), "includeDesignations", "excludeNested", "activeOnly", "offset", "count")) {
|
||||
focus.getExpansion().addParameter().setName(p.getName()).setValue(p.getValue());
|
||||
|
@ -642,6 +643,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
throw fail("Unable to find imported value set " + value);
|
||||
}
|
||||
}
|
||||
checkCanonical(exp, vs);
|
||||
if (noInactive) {
|
||||
expParams = expParams.copy();
|
||||
expParams.addParameter("activeOnly", true);
|
||||
|
@ -714,12 +716,12 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
|
||||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws FHIRException, ETooCostly {
|
||||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
for (ValueSetExpansionContainsComponent c : list) {
|
||||
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
|
||||
ValueSetExpansionContainsComponent np = addCode(dwc, c.getSystem(), c.getCode(), c.getDisplay(), vsSrc.getLanguage(), parent, null, expParams, c.getAbstract(), c.getInactive(), c.getExtensionString(ToolingExtensions.EXT_DEFINITION),
|
||||
filter, noInactive, false, vsProps, null, c.getProperty(), null, c.getExtension());
|
||||
copyImportContains(c.getContains(), np, expParams, filter, noInactive, vsProps, vsSrc);
|
||||
filter, noInactive, false, vsProps, null, c.getProperty(), null, c.getExtension(), exp);
|
||||
copyImportContains(c.getContains(), np, expParams, filter, noInactive, vsProps, vsSrc, exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -734,9 +736,10 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if (imports.isEmpty()) // though this is not supposed to be the case
|
||||
return;
|
||||
ValueSet base = imports.get(0);
|
||||
checkCanonical(exp, base);
|
||||
imports.remove(0);
|
||||
base.checkNoModifiers("Imported ValueSet", "expanding");
|
||||
copyImportContains(base.getExpansion().getContains(), null, expParams, imports, noInactive, base.getExpansion().getProperty(), base);
|
||||
copyImportContains(base.getExpansion().getContains(), null, expParams, imports, noInactive, base.getExpansion().getProperty(), base, exp);
|
||||
} else {
|
||||
CodeSystem cs = context.fetchSupplementedCodeSystem(inc.getSystem());
|
||||
if (ValueSetUtilities.isServerSide(inc.getSystem()) || (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
||||
|
@ -783,7 +786,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
for (ValueSetExpansionContainsComponent cc : vs.getExpansion().getContains()) {
|
||||
addCodeAndDescendents(dwc, cc, null, expParams, imports, noInactive, vsProps, vs);
|
||||
addCodeAndDescendents(dwc, cc, null, expParams, imports, noInactive, vsProps, vs, exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,6 +798,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
else
|
||||
throw failTSE("Unable to find code system " + inc.getSystem().toString());
|
||||
}
|
||||
checkCanonical(exp, cs);
|
||||
cs.checkNoModifiers("Code System", "expanding");
|
||||
if (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT)
|
||||
throw failTSE("Code system " + inc.getSystem().toString() + " is incomplete");
|
||||
|
@ -813,7 +817,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||
// special case - add all the code system
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(dwc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), null);
|
||||
addCodeAndDescendents(dwc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), null, exp);
|
||||
}
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
|
@ -846,7 +850,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
isAbstract = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||
}
|
||||
addCode(dwc, inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def == null ? null : def.getDisplay(), c.hasDisplay() ? vsSrc.getLanguage() : cs.getLanguage(), null, mergeDesignations(def, convertDesignations(c.getDesignation())),
|
||||
expParams, isAbstract, inactive, def == null ? null : def.getDefinition(), imports, noInactive, false, exp.getProperty(), def != null ? def.getProperty() : null, null, def == null ? null : def.getExtension(), c.getExtension());
|
||||
expParams, isAbstract, inactive, def == null ? null : def.getDefinition(), imports, noInactive, false, exp.getProperty(), def != null ? def.getProperty() : null, null, def == null ? null : def.getExtension(), c.getExtension(), exp);
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 0) {
|
||||
|
@ -876,14 +880,14 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (def == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters, exp);
|
||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISNOTA) {
|
||||
// special: all codes in the target code system that are not under the value
|
||||
ConceptDefinitionComponent defEx = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (defEx == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters, exp);
|
||||
}
|
||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
||||
// special: all codes in the target code system under the value
|
||||
|
@ -891,11 +895,11 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if (def == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters, exp);
|
||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||
for (ConceptDefinitionComponent c : children)
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters, exp);
|
||||
}
|
||||
|
||||
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
||||
|
@ -907,18 +911,18 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if (def.getDisplay().contains(fc.getValue()) && passesOtherFilters(filters, cs, def.getCode())) {
|
||||
for (String code : getCodesForConcept(def, expParams)) {
|
||||
ValueSetExpansionContainsComponent t = addCode(wc, inc.getSystem(), code, def.getDisplay(), cs.getLanguage(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||
def.getDefinition(), imports, noInactive, false, exp.getProperty(), def.getProperty(), null, def.getExtension(), null);
|
||||
def.getDefinition(), imports, noInactive, false, exp.getProperty(), def.getProperty(), null, def.getExtension(), null, exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isDefinedProperty(cs, fc.getProperty())) {
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(allErrors, fc, getPropertyDefinition(cs, fc.getProperty())), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(allErrors, fc, getPropertyDefinition(cs, fc.getProperty())), noInactive, exp.getProperty(), filters, exp);
|
||||
}
|
||||
} else if ("code".equals(fc.getProperty()) && fc.getOp() == FilterOperator.REGEX) {
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new RegexFilter(allErrors, fc.getValue()), noInactive, exp.getProperty(), filters);
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new RegexFilter(allErrors, fc.getValue()), noInactive, exp.getProperty(), filters, exp);
|
||||
}
|
||||
} else {
|
||||
throw fail("Filter by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
package org.hl7.fhir.r5.terminologies.utilities;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
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.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.StandardsStatus;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
||||
public class ValueSetProcessBase {
|
||||
|
||||
protected IWorkerContext context;
|
||||
|
||||
public static class AlternateCodesProcessingRules {
|
||||
private boolean all;
|
||||
private List<String> uses = new ArrayList<>();
|
||||
|
@ -77,6 +88,88 @@ public class ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
protected List<OperationOutcomeIssueComponent> makeIssue(IssueSeverity level, IssueType type, String location, String message) {
|
||||
OperationOutcomeIssueComponent result = new OperationOutcomeIssueComponent();
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR);
|
||||
break;
|
||||
case FATAL:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.FATAL);
|
||||
break;
|
||||
case INFORMATION:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION);
|
||||
break;
|
||||
case WARNING:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING);
|
||||
break;
|
||||
}
|
||||
result.setCode(type);
|
||||
result.addLocation(location);
|
||||
result.getDetails().setText(message);
|
||||
ArrayList<OperationOutcomeIssueComponent> list = new ArrayList<>();
|
||||
list.add(result);
|
||||
return list;
|
||||
}
|
||||
|
||||
public void checkCanonical(List<OperationOutcomeIssueComponent> issues, String path, CanonicalResource resource) {
|
||||
if (resource != null) {
|
||||
StandardsStatus standardsStatus = ToolingExtensions.getStandardsStatus(resource);
|
||||
if (standardsStatus == StandardsStatus.DEPRECATED) {
|
||||
addToIssues(issues, makeStatusIssue(path, "deprecated", I18nConstants.MSG_DEPRECATED, resource));
|
||||
} else if (standardsStatus == StandardsStatus.WITHDRAWN) {
|
||||
addToIssues(issues, makeStatusIssue(path, "withdrawn", I18nConstants.MSG_WITHDRAWN, resource));
|
||||
} else if (resource.getStatus() == PublicationStatus.RETIRED) {
|
||||
addToIssues(issues, makeStatusIssue(path, "retired", I18nConstants.MSG_RETIRED, resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<OperationOutcomeIssueComponent> makeStatusIssue(String path, String id, String msg, CanonicalResource resource) {
|
||||
List<OperationOutcomeIssueComponent> iss = makeIssue(IssueSeverity.INFORMATION, IssueType.EXPIRED, path, context.formatMessage(msg, resource.getVersionedUrl()));
|
||||
|
||||
// this is a testing hack - see TerminologyServiceTests
|
||||
iss.get(0).setUserData("status-msg-name", "warning-"+id);
|
||||
iss.get(0).setUserData("status-msg-value", new UriType(resource.getVersionedUrl()));
|
||||
|
||||
return iss;
|
||||
}
|
||||
|
||||
private void addToIssues(List<OperationOutcomeIssueComponent> issues, List<OperationOutcomeIssueComponent> toAdd) {
|
||||
for (OperationOutcomeIssueComponent t : toAdd) {
|
||||
boolean found = false;
|
||||
for (OperationOutcomeIssueComponent i : issues) {
|
||||
if (i.getSeverity() == t.getSeverity() && i.getCode() == t.getCode() && i.getDetails().getText().equals(t.getDetails().getText())) { // ignore location
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
issues.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkCanonical(ValueSetExpansionComponent params, CanonicalResource resource) {
|
||||
if (resource != null) {
|
||||
StandardsStatus standardsStatus = ToolingExtensions.getStandardsStatus(resource);
|
||||
if (standardsStatus == StandardsStatus.DEPRECATED) {
|
||||
if (!params.hasParameterValue("warning-deprecated", resource.getVersionedUrl())) {
|
||||
params.addParameter("warning-deprecated", new UriType(resource.getVersionedUrl()));
|
||||
}
|
||||
} else if (standardsStatus == StandardsStatus.WITHDRAWN) {
|
||||
if (!params.hasParameterValue("warning-withdrawn", resource.getVersionedUrl())) {
|
||||
params.addParameter("warning-withdrawn", new UriType(resource.getVersionedUrl()));
|
||||
}
|
||||
} else if (resource.getStatus() == PublicationStatus.RETIRED) {
|
||||
if (!params.hasParameterValue("warning-retired", resource.getVersionedUrl())) {
|
||||
params.addParameter("warning-retired", new UriType(resource.getVersionedUrl()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected AlternateCodesProcessingRules altCodeParams = new AlternateCodesProcessingRules(false);
|
||||
protected AlternateCodesProcessingRules allAltCodes = new AlternateCodesProcessingRules(true);
|
||||
}
|
||||
|
|
|
@ -97,7 +97,6 @@ import com.google.j2objc.annotations.ReflectionSupport.Level;
|
|||
public class ValueSetValidator extends ValueSetProcessBase {
|
||||
|
||||
private ValueSet valueset;
|
||||
private IWorkerContext context;
|
||||
private Map<String, ValueSetValidator> inner = new HashMap<>();
|
||||
private ValidationOptions options;
|
||||
private ValidationContextCarrier localContext;
|
||||
|
@ -229,7 +228,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
|
||||
for (Coding c : code.getCoding()) {
|
||||
b.append(c.getSystem()+(c.hasVersion() ? "|"+c.getVersion() : "")+"#"+c.getCode());
|
||||
Boolean ok = codeInValueSet(c.getSystem(), c.getVersion(), c.getCode(), info);
|
||||
Boolean ok = codeInValueSet(path, c.getSystem(), c.getVersion(), c.getCode(), info);
|
||||
if (ok == null && result != null && result == false) {
|
||||
result = null;
|
||||
} else if (ok != null && ok) {
|
||||
|
@ -338,30 +337,6 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
return versionTest == null && VersionUtilities.versionsMatch(versionTest, versionActual);
|
||||
}
|
||||
|
||||
private List<OperationOutcomeIssueComponent> makeIssue(IssueSeverity level, IssueType type, String location, String message) {
|
||||
OperationOutcomeIssueComponent result = new OperationOutcomeIssueComponent();
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR);
|
||||
break;
|
||||
case FATAL:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.FATAL);
|
||||
break;
|
||||
case INFORMATION:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION);
|
||||
break;
|
||||
case WARNING:
|
||||
result.setSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING);
|
||||
break;
|
||||
}
|
||||
result.setCode(type);
|
||||
result.addLocation(location);
|
||||
result.getDetails().setText(message);
|
||||
ArrayList<OperationOutcomeIssueComponent> list = new ArrayList<>();
|
||||
list.add(result);
|
||||
return list;
|
||||
}
|
||||
|
||||
public ValidationResult validateCode(Coding code) throws FHIRException {
|
||||
return validateCode("Coding", code);
|
||||
}
|
||||
|
@ -375,6 +350,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
boolean inInclude = false;
|
||||
List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
checkCanonical(issues, path, valueset);
|
||||
|
||||
String system = code.hasSystem() ? code.getSystem() : getValueSetSystemOrNull();
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
|
@ -434,6 +410,8 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
checkCanonical(issues, path, cs);
|
||||
}
|
||||
if (cs != null && cs.hasSupplements()) {
|
||||
String msg = context.formatMessage(I18nConstants.CODESYSTEM_CS_NO_SUPPLEMENT, cs.getUrl());
|
||||
|
@ -462,6 +440,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
throw new FHIRException("Unable to evaluate based on empty code system");
|
||||
}
|
||||
res = validateCode(path, code, cs, null);
|
||||
res.setIssues(issues);
|
||||
} else if (cs == null && valueset.hasExpansion() && inExpansion) {
|
||||
// we just take the value set as face value then
|
||||
res = new ValidationResult(system, wv, new ConceptDefinitionComponent().setCode(code.getCode()).setDisplay(code.getDisplay()), code.getDisplay());
|
||||
|
@ -486,7 +465,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
// then, if we have a value set, we check it's in the value set
|
||||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
if ((res==null || res.isOk())) {
|
||||
Boolean ok = codeInValueSet(system, wv, code.getCode(), info);
|
||||
Boolean ok = codeInValueSet(path, system, wv, code.getCode(), info);
|
||||
if (ok == null || !ok) {
|
||||
if (res == null) {
|
||||
res = new ValidationResult((IssueSeverity) null, null, info.getIssues());
|
||||
|
@ -982,14 +961,11 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
public Boolean codeInValueSet(String system, String version, String code, ValidationProcessInfo info) throws FHIRException {
|
||||
return codeInValueSet("code", system, version, code, info);
|
||||
}
|
||||
|
||||
public Boolean codeInValueSet(String path, String system, String version, String code, ValidationProcessInfo info) throws FHIRException {
|
||||
if (valueset == null) {
|
||||
return false;
|
||||
}
|
||||
checkCanonical(info.getIssues(), path, valueset);
|
||||
Boolean result = false;
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
|
||||
|
@ -1029,15 +1005,15 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
if (isValueSetUnionImports()) {
|
||||
ok = false;
|
||||
for (UriType uri : vsi.getValueSet()) {
|
||||
if (inImport(uri.getValue(), system, version, code)) {
|
||||
if (inImport(path, uri.getValue(), system, version, code, info)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok = inImport(vsi.getValueSet().get(0).getValue(), system, version, code);
|
||||
ok = inImport(path, vsi.getValueSet().get(0).getValue(), system, version, code, info);
|
||||
for (int i = 1; i < vsi.getValueSet().size(); i++) {
|
||||
UriType uri = vsi.getValueSet().get(i);
|
||||
ok = ok && inImport(uri.getValue(), system, version, code);
|
||||
ok = ok && inImport(path, uri.getValue(), system, version, code, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1097,6 +1073,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
return null;
|
||||
}
|
||||
} else {
|
||||
checkCanonical(info.getIssues(), path, cs);
|
||||
if (vsi.hasFilter()) {
|
||||
ok = true;
|
||||
for (ConceptSetFilterComponent f : vsi.getFilter()) {
|
||||
|
@ -1231,12 +1208,12 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
return vsc;
|
||||
}
|
||||
|
||||
private boolean inImport(String uri, String system, String version, String code) throws FHIRException {
|
||||
private boolean inImport(String path, String uri, String system, String version, String code, ValidationProcessInfo info) throws FHIRException {
|
||||
ValueSetValidator vs = getVs(uri);
|
||||
if (vs == null) {
|
||||
return false;
|
||||
} else {
|
||||
Boolean ok = vs.codeInValueSet(system, version, code, null);
|
||||
Boolean ok = vs.codeInValueSet(path, system, version, code, info);
|
||||
return ok != null && ok;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class CompareUtilities extends BaseTestingUtilities {
|
|||
String result = compareXml(expected, actual);
|
||||
if (result != null && SHOW_DIFF) {
|
||||
String diff = getDiffTool();
|
||||
if (new File(diff).exists() || Utilities.isToken(diff)) {
|
||||
if (diff != null && new File(diff).exists() || Utilities.isToken(diff)) {
|
||||
Runtime.getRuntime().exec(new String[]{diff, expected, actual});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,8 +65,9 @@ public class CSFile extends File {
|
|||
//attempt to open a file triggers a directory listing
|
||||
if (exists())
|
||||
{
|
||||
if(!this.getCanonicalFile().getName().equals(this.getName()))
|
||||
if(!this.getCanonicalFile().getName().equals(this.getName())) {
|
||||
throw new Error("Case mismatch of file "+ pathname+": found "+this.getCanonicalFile().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
|
||||
public enum StandardsStatus {
|
||||
|
||||
EXTERNAL, INFORMATIVE, DRAFT, TRIAL_USE, DEPRECATED, NORMATIVE;
|
||||
EXTERNAL, INFORMATIVE, DRAFT, TRIAL_USE, DEPRECATED, NORMATIVE, WITHDRAWN;
|
||||
|
||||
public String toDisplay() {
|
||||
switch (this) {
|
||||
|
@ -51,6 +51,8 @@ public enum StandardsStatus {
|
|||
return "External";
|
||||
case DEPRECATED:
|
||||
return "Deprecated";
|
||||
case WITHDRAWN:
|
||||
return "Withdrawn";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
@ -66,9 +68,11 @@ public enum StandardsStatus {
|
|||
case INFORMATIVE:
|
||||
return "informative";
|
||||
case DEPRECATED:
|
||||
return "deprecated";
|
||||
return "deprecated";
|
||||
case EXTERNAL:
|
||||
return "external";
|
||||
case WITHDRAWN:
|
||||
return "Withdrawn";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
@ -93,6 +97,8 @@ public enum StandardsStatus {
|
|||
return EXTERNAL;
|
||||
if (value.equalsIgnoreCase("DEPRECATED"))
|
||||
return DEPRECATED;
|
||||
if (value.equalsIgnoreCase("WITHDRAWN"))
|
||||
return WITHDRAWN;
|
||||
throw new FHIRException("Incorrect Standards Status '"+value+"'");
|
||||
}
|
||||
|
||||
|
@ -110,6 +116,8 @@ public enum StandardsStatus {
|
|||
return "XD";
|
||||
case EXTERNAL:
|
||||
return "X";
|
||||
case WITHDRAWN:
|
||||
return "W";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
@ -125,6 +133,7 @@ public enum StandardsStatus {
|
|||
case INFORMATIVE:
|
||||
return "#ffffe6";
|
||||
case DEPRECATED:
|
||||
case WITHDRAWN:
|
||||
return "#ffcccc";
|
||||
case EXTERNAL:
|
||||
return "#e6ffff";
|
||||
|
@ -143,6 +152,7 @@ public enum StandardsStatus {
|
|||
case INFORMATIVE:
|
||||
return "#ffffec";
|
||||
case DEPRECATED:
|
||||
case WITHDRAWN:
|
||||
return "#ffcccc";
|
||||
case EXTERNAL:
|
||||
return "#ecffff";
|
||||
|
@ -159,6 +169,8 @@ public enum StandardsStatus {
|
|||
return (tgtSS == NORMATIVE || tgtSS == EXTERNAL );
|
||||
if (this == DEPRECATED)
|
||||
return (tgtSS == DEPRECATED );
|
||||
if (this == WITHDRAWN)
|
||||
return (tgtSS == WITHDRAWN );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -307,7 +307,18 @@ public class Utilities {
|
|||
CSFile src = new CSFile(sourceFolder);
|
||||
if (!src.exists())
|
||||
throw new FHIRException("Folder " + sourceFolder + " not found");
|
||||
createDirectory(destFolder);
|
||||
File dst = new File(destFolder);
|
||||
if(!dst.getCanonicalFile().getName().equals(dst.getName())) {
|
||||
File tmp = new File(destFolder+System.currentTimeMillis());
|
||||
if (!dst.renameTo(tmp)) {
|
||||
throw new IOException("fixing case from "+dst.getCanonicalFile().getName()+" to "+tmp.getName()+" failed");
|
||||
}
|
||||
if (!tmp.renameTo(dst)) {
|
||||
throw new IOException("fixing case from "+tmp.getCanonicalFile().getName()+" to "+dst.getName()+" failed");
|
||||
}
|
||||
} else if (!dst.exists()) {
|
||||
createDirectory(destFolder);
|
||||
}
|
||||
|
||||
String[] files = src.list();
|
||||
for (String f : files) {
|
||||
|
@ -318,7 +329,7 @@ public class Utilities {
|
|||
} else {
|
||||
if (notifier != null)
|
||||
notifier.copyFile(sourceFolder + File.separator + f, destFolder + File.separator + f);
|
||||
copyFile(new CSFile(sourceFolder + File.separator + f), new CSFile(destFolder + File.separator + f));
|
||||
copyFile(new CSFile(sourceFolder + File.separator + f), new /*CS*/File(destFolder + File.separator + f)); // case doesn't have to match on the target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -358,6 +369,10 @@ public class Utilities {
|
|||
createDirectory(destFile.getParent());
|
||||
}
|
||||
destFile.createNewFile();
|
||||
} else if (!destFile.getCanonicalFile().getName().equals(destFile.getName())) {
|
||||
// case mismatch
|
||||
destFile.delete();
|
||||
destFile.createNewFile();
|
||||
}
|
||||
|
||||
FileInputStream source = null;
|
||||
|
|
|
@ -950,6 +950,9 @@ public class I18nConstants {
|
|||
public static final String FHIRPATH_OFTYPE_IMPOSSIBLE = "FHIRPATH_OFTYPE_IMPOSSIBLE";
|
||||
public static final String ED_SEARCH_EXPRESSION_ERROR = "ED_SEARCH_EXPRESSION_ERROR";
|
||||
public static final String SD_EXTENSION_URL_MISMATCH = "SD_EXTENSION_URL_MISMATCH";
|
||||
public static final String MSG_DEPRECATED = "MSG_DEPRECATED";
|
||||
public static final String MSG_WITHDRAWN = "MSG_WITHDRAWN";
|
||||
public static final String MSG_RETIRED = "MSG_RETIRED";
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1266,6 +1266,11 @@ public class NpmPackage {
|
|||
return Utilities.existsInList(npm.asString("type"), "fhir.core", "Core");
|
||||
}
|
||||
|
||||
public boolean isCoreExamples() {
|
||||
return name().startsWith("hl7.fhir.r") && name().endsWith(".examples");
|
||||
}
|
||||
|
||||
|
||||
public boolean isTx() {
|
||||
return npm.asString("name").startsWith("hl7.terminology");
|
||||
}
|
||||
|
@ -1369,5 +1374,5 @@ public class NpmPackage {
|
|||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1005,4 +1005,7 @@ FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT = The left side is inherently a collec
|
|||
FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT = The right side is inherently a collection, and so this expression ''{0}'' may fail or return false if there is more than one item in the content being evaluated
|
||||
FHIRPATH_OFTYPE_IMPOSSIBLE = The type specified in ofType is {1} which is not a possible candidate for the existing types ({0}) in the expression {2}. Check the paths and types to be sure this is what is intended
|
||||
ED_SEARCH_EXPRESSION_ERROR = Error in search expression ''{0}'': {1}
|
||||
SD_EXTENSION_URL_MISMATCH = The fixed value for the extension URL is {1} which doesn''t match the canonical URL {0}
|
||||
SD_EXTENSION_URL_MISMATCH = The fixed value for the extension URL is {1} which doesn''t match the canonical URL {0}
|
||||
MSG_DEPRECATED = Reference to deprecated item {0}
|
||||
MSG_WITHDRAWN = Reference to withdrawn item {0}
|
||||
MSG_RETIRED = Reference to retired item {0}
|
||||
|
|
|
@ -422,5 +422,46 @@ class UtilitiesTest {
|
|||
Assertions.assertFalse("\u0009\n\u000B\u000C\r\u0020\u0085\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000".matches(".+"));
|
||||
Assertions.assertFalse("\u0009\n\u000B\u000C\r\u0020\u0085\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000".matches("^.+$"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("directory copy case tests")
|
||||
void testFDirectoryCopy() throws IOException {
|
||||
String src = Utilities.path("[tmp]", "test", "copy-source");
|
||||
String dst = Utilities.path("[tmp]", "test", "copy-dest");
|
||||
makeDir (src);
|
||||
makeFile(Utilities.path(src, "Test.txt"), "source1");
|
||||
makeDir (Utilities.path(src, "SUB"));
|
||||
makeFile(Utilities.path(src, "SUB", "TEST.txt"), "source2");
|
||||
|
||||
makeDir (dst);
|
||||
makeFile(Utilities.path(dst, "test.txt"), "dest1");
|
||||
makeDir (Utilities.path(dst, "sub"));
|
||||
makeFile(Utilities.path(dst, "sub", "test.txt"), "dest2");
|
||||
|
||||
Utilities.copyDirectory(src, dst, null);
|
||||
|
||||
checkDir (dst);
|
||||
checkFile(Utilities.path(dst, "Test.txt"), "source1");
|
||||
checkDir (Utilities.path(dst, "SUB"));
|
||||
checkFile(Utilities.path(dst, "SUB", "TEST.txt"), "source2");
|
||||
}
|
||||
|
||||
private void checkFile(String path, String content) throws IOException {
|
||||
Assertions.assertTrue(new CSFile(path).exists());
|
||||
Assertions.assertEquals(content, TextFile.fileToString(path));
|
||||
}
|
||||
|
||||
private void checkDir(String path) throws IOException {
|
||||
Assertions.assertTrue(new CSFile(path).exists());
|
||||
}
|
||||
|
||||
private void makeFile(String path, String content) throws IOException {
|
||||
TextFile.stringToFile(content, path);
|
||||
}
|
||||
|
||||
private void makeDir(String path) throws IOException {
|
||||
Utilities.createDirectory(path);
|
||||
Utilities.clearDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -520,12 +520,14 @@ public class IgLoader implements IValidationEngineLoader {
|
|||
}
|
||||
}
|
||||
|
||||
if (loadInContext) {
|
||||
// getContext().getLoadedPackages().add(pi.name() + "#" + pi.version());
|
||||
getContext().loadFromPackage(pi, ValidatorUtils.loaderForVersion(pi.fhirVersion()));
|
||||
}
|
||||
for (String s : pi.listResources("CodeSystem", "ConceptMap", "ImplementationGuide", "CapabilityStatement", "SearchParameter", "Conformance", "StructureMap", "ValueSet", "StructureDefinition")) {
|
||||
res.put(s, TextFile.streamToBytes(pi.load("package", s)));
|
||||
if (!pi.isCoreExamples()) {
|
||||
if (loadInContext) {
|
||||
// getContext().getLoadedPackages().add(pi.name() + "#" + pi.version());
|
||||
getContext().loadFromPackage(pi, ValidatorUtils.loaderForVersion(pi.fhirVersion()));
|
||||
}
|
||||
for (String s : pi.listResources("CodeSystem", "ConceptMap", "ImplementationGuide", "CapabilityStatement", "SearchParameter", "Conformance", "StructureMap", "ValueSet", "StructureDefinition")) {
|
||||
res.put(s, TextFile.streamToBytes(pi.load("package", s)));
|
||||
}
|
||||
}
|
||||
String ini = "[FHIR]\r\nversion=" + pi.fhirVersion() + "\r\n";
|
||||
res.put("version.info", ini.getBytes());
|
||||
|
|
|
@ -3,7 +3,11 @@ package org.hl7.fhir.validation.special;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hl7.fhir.ParametersParameter;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
|
@ -16,8 +20,14 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
|||
public class TxTesterSorters {
|
||||
|
||||
|
||||
|
||||
public static void sortParameters(Parameters po) {
|
||||
Collections.sort(po.getParameter(), new TxTesterSorters.ParameterSorter());
|
||||
for (ParametersParameterComponent p : po.getParameter()) {
|
||||
if (p.getResource() != null && p.getResource() instanceof OperationOutcome) {
|
||||
Collections.sort(((OperationOutcome) p.getResource()).getIssue(), new TxTesterSorters.OperationIssueSorter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,7 +53,24 @@ public class TxTesterSorters {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class OperationIssueSorter implements Comparator<OperationOutcomeIssueComponent> {
|
||||
|
||||
@Override
|
||||
public int compare(OperationOutcomeIssueComponent o1, OperationOutcomeIssueComponent o2) {
|
||||
if (o1.hasSeverity() && o2.hasSeverity() && o1.getSeverity() != o2.getSeverity()) {
|
||||
return o1.getSeverity().compareTo(o2.getSeverity());
|
||||
}
|
||||
if (o1.hasCode() && o2.hasCode() && o1.getCode() != o2.getCode()) {
|
||||
return o1.getCode().compareTo(o2.getCode());
|
||||
}
|
||||
if (o1.getDetails().hasText() && o2.getDetails().hasText() && !o1.getDetails().getText().equals(o2.getDetails().getText())) {
|
||||
return o1.getDetails().getText().compareTo(o2.getDetails().getText());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DesignationSorter implements Comparator<ConceptReferenceDesignationComponent> {
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue