Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core
This commit is contained in:
commit
5259bf9847
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
## Other code changes
|
## Other code changes
|
||||||
|
|
||||||
* no changes
|
* More comprehensive internationalization phrase coverage reporting.
|
||||||
|
* Shim interfaces and classes to support clinical reasoning project updates.
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
@ -1,5 +1,5 @@
|
||||||
Locale,Coverage #,Coverage %
|
Locale,Coverage #,Coverage %
|
||||||
de,869,43%
|
de,869,43%
|
||||||
es,740,37%
|
es,740,36%
|
||||||
ja,935,46%
|
ja,935,46%
|
||||||
nl,873,43%
|
nl,873,43%
|
||||||
|
|
|
|
@ -277,7 +277,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
protected boolean canRunWithoutTerminology;
|
protected boolean canRunWithoutTerminology;
|
||||||
protected boolean noTerminologyServer;
|
protected boolean noTerminologyServer;
|
||||||
private int expandCodesLimit = 1000;
|
private int expandCodesLimit = 1000;
|
||||||
protected ILoggingService logger = new SystemOutLoggingService();
|
protected org.hl7.fhir.r5.context.ILoggingService logger = new SystemOutLoggingService();
|
||||||
protected Parameters expParameters;
|
protected Parameters expParameters;
|
||||||
private Map<String, PackageInformation> packages = new HashMap<>();
|
private Map<String, PackageInformation> packages = new HashMap<>();
|
||||||
|
|
||||||
|
@ -1991,7 +1991,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
this.canRunWithoutTerminology = canRunWithoutTerminology;
|
this.canRunWithoutTerminology = canRunWithoutTerminology;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLogger(@Nonnull ILoggingService logger) {
|
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2816,7 +2816,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ILoggingService getLogger() {
|
public org.hl7.fhir.r5.context.ILoggingService getLogger() {
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,18 @@ import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public interface IWorkerContext {
|
public interface IWorkerContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
@deprecated This interface only exists to provide backward compatibility for the following two projects:
|
||||||
|
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
|
||||||
|
<a href="https://github.com/cqframework/clinical_quality_language/">clinical_quality-language</a>
|
||||||
|
|
||||||
|
Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards
|
||||||
|
compatibility with core version 6.1.2.2
|
||||||
|
**/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
public interface ILoggingService extends org.hl7.fhir.r5.context.ILoggingService{
|
||||||
|
|
||||||
|
}
|
||||||
public class OIDDefinitionComparer implements Comparator<OIDDefinition> {
|
public class OIDDefinitionComparer implements Comparator<OIDDefinition> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -630,8 +642,8 @@ public interface IWorkerContext {
|
||||||
// todo: figure these out
|
// todo: figure these out
|
||||||
public Map<String, NamingSystem> getNSUrlMap();
|
public Map<String, NamingSystem> getNSUrlMap();
|
||||||
|
|
||||||
public void setLogger(@Nonnull ILoggingService logger);
|
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger);
|
||||||
public ILoggingService getLogger();
|
public org.hl7.fhir.r5.context.ILoggingService getLogger();
|
||||||
|
|
||||||
public boolean isNoTerminologyServer();
|
public boolean isNoTerminologyServer();
|
||||||
public Set<String> getCodeSystemsUsed();
|
public Set<String> getCodeSystemsUsed();
|
||||||
|
|
|
@ -214,7 +214,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
||||||
private final boolean allowLoadingDuplicates;
|
private final boolean allowLoadingDuplicates;
|
||||||
|
|
||||||
@With
|
@With
|
||||||
private final ILoggingService loggingService;
|
private final org.hl7.fhir.r5.context.ILoggingService loggingService;
|
||||||
|
|
||||||
public SimpleWorkerContextBuilder() {
|
public SimpleWorkerContextBuilder() {
|
||||||
cacheTerminologyClientErrors = false;
|
cacheTerminologyClientErrors = false;
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
package org.hl7.fhir.r5.model;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.fhirpath.TypeDetails;
|
||||||
|
import org.hl7.fhir.utilities.SourceLocation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@deprecated This interface only exists to provide backward compatibility for the following two projects:
|
||||||
|
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
|
||||||
|
<a href="https://github.com/cqframework/clinical_quality_language/">clinical_quality-language</a>
|
||||||
|
|
||||||
|
Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards
|
||||||
|
compatibility with core version 6.1.2.2
|
||||||
|
**/
|
||||||
|
public class ExpressionNode extends org.hl7.fhir.r5.fhirpath.ExpressionNode{
|
||||||
|
|
||||||
|
private final org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode;
|
||||||
|
public ExpressionNode(int uniqueId) {
|
||||||
|
super(0);
|
||||||
|
wrappedExpressionNode = new org.hl7.fhir.r5.fhirpath.ExpressionNode(uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionNode(org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode) {
|
||||||
|
super(0);
|
||||||
|
this.wrappedExpressionNode = wrappedExpressionNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return wrappedExpressionNode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return wrappedExpressionNode.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
wrappedExpressionNode.setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base getConstant() {
|
||||||
|
return wrappedExpressionNode.getConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConstant(Base constant) {
|
||||||
|
wrappedExpressionNode.setConstant(constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getFunction() {
|
||||||
|
return wrappedExpressionNode.getFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFunction(Function function) {
|
||||||
|
wrappedExpressionNode.setFunction(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isProximal() {
|
||||||
|
return wrappedExpressionNode.isProximal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProximal(boolean proximal) {
|
||||||
|
wrappedExpressionNode.setProximal(proximal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Operation getOperation() {
|
||||||
|
return wrappedExpressionNode.getOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOperation(Operation operation) {
|
||||||
|
wrappedExpressionNode.setOperation(operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.hl7.fhir.r5.fhirpath.ExpressionNode getInner() {
|
||||||
|
return wrappedExpressionNode.getInner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setInner(org.hl7.fhir.r5.fhirpath.ExpressionNode value) {
|
||||||
|
wrappedExpressionNode.setInner(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.hl7.fhir.r5.fhirpath.ExpressionNode getOpNext() {
|
||||||
|
return wrappedExpressionNode.getOpNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOpNext(org.hl7.fhir.r5.fhirpath.ExpressionNode value) {
|
||||||
|
wrappedExpressionNode.setOpNext(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<org.hl7.fhir.r5.fhirpath.ExpressionNode> getParameters() {
|
||||||
|
return wrappedExpressionNode.getParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkName() {
|
||||||
|
return wrappedExpressionNode.checkName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Kind getKind() {
|
||||||
|
return wrappedExpressionNode.getKind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setKind(Kind kind) {
|
||||||
|
wrappedExpressionNode.setKind(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.hl7.fhir.r5.fhirpath.ExpressionNode getGroup() {
|
||||||
|
return wrappedExpressionNode.getGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGroup(org.hl7.fhir.r5.fhirpath.ExpressionNode group) {
|
||||||
|
wrappedExpressionNode.setGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceLocation getStart() {
|
||||||
|
return wrappedExpressionNode.getStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStart(SourceLocation start) {
|
||||||
|
wrappedExpressionNode.setStart(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceLocation getEnd() {
|
||||||
|
return wrappedExpressionNode.getEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnd(SourceLocation end) {
|
||||||
|
wrappedExpressionNode.setEnd(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceLocation getOpStart() {
|
||||||
|
return wrappedExpressionNode.getOpStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOpStart(SourceLocation opStart) {
|
||||||
|
wrappedExpressionNode.setOpStart(opStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceLocation getOpEnd() {
|
||||||
|
return wrappedExpressionNode.getOpEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOpEnd(SourceLocation opEnd) {
|
||||||
|
wrappedExpressionNode.setOpEnd(opEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUniqueId() {
|
||||||
|
return wrappedExpressionNode.getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parameterCount() {
|
||||||
|
return wrappedExpressionNode.parameterCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String Canonical() {
|
||||||
|
return wrappedExpressionNode.Canonical();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String summary() {
|
||||||
|
return wrappedExpressionNode.summary();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String check() {
|
||||||
|
return wrappedExpressionNode.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeDetails getTypes() {
|
||||||
|
return wrappedExpressionNode.getTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTypes(TypeDetails types) {
|
||||||
|
wrappedExpressionNode.setTypes(types);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeDetails getOpTypes() {
|
||||||
|
return wrappedExpressionNode.getOpTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOpTypes(TypeDetails opTypes) {
|
||||||
|
wrappedExpressionNode.setOpTypes(opTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getDistalNames() {
|
||||||
|
return wrappedExpressionNode.getDistalNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullSet() {
|
||||||
|
return wrappedExpressionNode.isNullSet();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@deprecated This interface only exists to provide backward compatibility for the following two projects:
|
||||||
|
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
|
||||||
|
<a href="https://github.com/cqframework/clinical_quality_language/">clinical_quality-language</a>
|
||||||
|
|
||||||
|
Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards
|
||||||
|
compatibility with core version 6.1.2.2
|
||||||
|
**/
|
||||||
|
public class FHIRPathEngine extends org.hl7.fhir.r5.fhirpath.FHIRPathEngine {
|
||||||
|
|
||||||
|
public interface IEvaluationContext extends org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext{ }
|
||||||
|
public FHIRPathEngine(IWorkerContext worker) {
|
||||||
|
super(worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.hl7.fhir.r5.model.ExpressionNode parse(String string) {
|
||||||
|
return new org.hl7.fhir.r5.model.ExpressionNode(super.parse(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Base> evaluate(Base base, org.hl7.fhir.r5.model.ExpressionNode expressionNode) {
|
||||||
|
return super.evaluate(base, expressionNode);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,82 @@
|
||||||
package org.hl7.fhir.utilities;
|
package org.hl7.fhir.utilities;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction that splits a canonical in form of {@code <url>|<version>} into a URL and a version part.
|
||||||
|
*/
|
||||||
public class CanonicalPair {
|
public class CanonicalPair {
|
||||||
|
|
||||||
private String url;
|
private final String url;
|
||||||
private String version;
|
private final String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static factory method, that invokes the {@link CanonicalPair#CanonicalPair(String) CanonicalPair constructor}
|
||||||
|
* with the given argument.
|
||||||
|
* @param target the canonical to be split. May be {@code null}.
|
||||||
|
* @return new instance of CanonicalPair
|
||||||
|
*/
|
||||||
|
public static CanonicalPair of(String target) {
|
||||||
|
return new CanonicalPair(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the given canonical and if needed splits off the version part.<p>
|
||||||
|
* The given parameter {@code target} is expected to be a canonical.
|
||||||
|
* @param target canonical to create a url, version pair from. May be {@code null}.
|
||||||
|
*/
|
||||||
public CanonicalPair(String target) {
|
public CanonicalPair(String target) {
|
||||||
if (target != null && target.contains("|")) {
|
int pipeIndex = target != null ? target.indexOf('|') : -1;
|
||||||
this.url = target.substring(0, target.indexOf("|"));
|
if (pipeIndex >= 0) {
|
||||||
this.version = target.substring(target.indexOf("|")+1);
|
this.url = target.substring(0, pipeIndex);
|
||||||
|
this.version = target.substring(pipeIndex+1);
|
||||||
} else {
|
} else {
|
||||||
this.url = target;
|
this.url = target;
|
||||||
this.version = null;
|
this.version = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the URL part of the canonical (everything before the {@code "|"} character, or the complete
|
||||||
|
* canonical if the character is not present). If the source
|
||||||
|
* @return URL part of the source canonical. May be {@code null}, if source canonical was {@code null}
|
||||||
|
*/
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version part of the source canonical (everything after the {@code "|"} character.
|
||||||
|
* @return version part of the canonical, may be {@code null}, if canonical was {@code null}, or canonical contains no
|
||||||
|
* {@code "|"} character.
|
||||||
|
*/
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the version part of the canonical is not {@code null}
|
||||||
|
* @return {@code true} if version is not {@code null}, otherwise {@code false}
|
||||||
|
*/
|
||||||
|
public boolean hasVersion() {
|
||||||
|
return version != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version of this pair, or the parameter {@code alternative},
|
||||||
|
* if the version of this pair is {@code null}.
|
||||||
|
* @param alternative to be returned from this method if the encapsulated version is {@code null}.
|
||||||
|
* @return either the held version, or {@code alternative}, if version is {@code null}
|
||||||
|
*/
|
||||||
|
public String getVersionOr(String alternative) {
|
||||||
|
return hasVersion() ? version : alternative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the encapsulated version of this pair is not {@code null} and not an empty string.
|
||||||
|
* @return {@code true} if the version of this pair is not {@code null} and not an empty string, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public boolean hasNonEmptyVersion() {
|
||||||
|
return StringUtils.isNotEmpty(version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
*/
|
*/
|
||||||
public class TerminologyServiceOptions extends ValidationOptions {
|
public class TerminologyServiceOptions extends ValidationOptions {
|
||||||
|
|
||||||
|
public TerminologyServiceOptions() { this(FhirPublication.R5); }
|
||||||
|
|
||||||
public TerminologyServiceOptions(FhirPublication fhirVersion) {
|
public TerminologyServiceOptions(FhirPublication fhirVersion) {
|
||||||
super(fhirVersion);
|
super(fhirVersion);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ public class ValidationOptions {
|
||||||
private boolean exampleOK = false;
|
private boolean exampleOK = false;
|
||||||
private FhirPublication fhirVersion;
|
private FhirPublication fhirVersion;
|
||||||
|
|
||||||
|
public ValidationOptions() { this(FhirPublication.R5); }
|
||||||
|
|
||||||
public ValidationOptions(FhirPublication fhirVersion) {
|
public ValidationOptions(FhirPublication fhirVersion) {
|
||||||
super();
|
super();
|
||||||
this.fhirVersion = fhirVersion;
|
this.fhirVersion = fhirVersion;
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package org.hl7.fhir.utilities;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class CanonicalPairTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalNull() {
|
||||||
|
var canonical = new CanonicalPair(null);
|
||||||
|
assertNull(canonical.getUrl());
|
||||||
|
assertNull(canonical.getVersion());
|
||||||
|
assertFalse(canonical.hasVersion());
|
||||||
|
assertFalse(canonical.hasNonEmptyVersion());
|
||||||
|
String expectedVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(expectedVer);
|
||||||
|
assertEquals(expectedVer, actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalEmpty() {
|
||||||
|
var url = "";
|
||||||
|
var canonical = new CanonicalPair(url);
|
||||||
|
assertEquals(url, canonical.getUrl());
|
||||||
|
assertFalse(canonical.hasVersion());
|
||||||
|
assertFalse(canonical.hasNonEmptyVersion());
|
||||||
|
String expectedVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(expectedVer);
|
||||||
|
assertEquals(expectedVer, actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalWithoutVersion() {
|
||||||
|
var url = "https://www.test.org";
|
||||||
|
var canonical = new CanonicalPair(url);
|
||||||
|
assertEquals(url, canonical.getUrl());
|
||||||
|
assertNull(canonical.getVersion());
|
||||||
|
assertFalse(canonical.hasVersion());
|
||||||
|
assertFalse(canonical.hasNonEmptyVersion());
|
||||||
|
String expectedVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(expectedVer);
|
||||||
|
assertEquals(expectedVer, actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalWithEmptyVersion() {
|
||||||
|
var expectedUrl = "https://www.test.org";
|
||||||
|
var url = expectedUrl + "|";
|
||||||
|
var canonical = new CanonicalPair(url);
|
||||||
|
assertEquals(expectedUrl, canonical.getUrl());
|
||||||
|
assertEquals("", canonical.getVersion());
|
||||||
|
assertTrue(canonical.hasVersion());
|
||||||
|
assertFalse(canonical.hasNonEmptyVersion());
|
||||||
|
String alternativeVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(alternativeVer);
|
||||||
|
assertEquals("", actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalWithVersion() {
|
||||||
|
var expectedUrl = "https://www.test.org";
|
||||||
|
var expectedVersion = "2.6";
|
||||||
|
var url = expectedUrl + "|" + expectedVersion;
|
||||||
|
var canonical = new CanonicalPair(url);
|
||||||
|
assertEquals(expectedUrl, canonical.getUrl());
|
||||||
|
assertEquals(expectedVersion, canonical.getVersion());
|
||||||
|
assertTrue(canonical.hasVersion());
|
||||||
|
assertTrue(canonical.hasNonEmptyVersion());
|
||||||
|
String alternativeVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(alternativeVer);
|
||||||
|
assertEquals(expectedVersion, actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCanonicalWithVersionIncludingPipe() {
|
||||||
|
var expectedUrl = "https://www.test.org";
|
||||||
|
var expectedVersion = "2024|05";
|
||||||
|
var url = expectedUrl + "|" + expectedVersion;
|
||||||
|
var canonical = new CanonicalPair(url);
|
||||||
|
assertEquals(expectedUrl, canonical.getUrl());
|
||||||
|
assertEquals(expectedVersion, canonical.getVersion());
|
||||||
|
assertTrue(canonical.hasVersion());
|
||||||
|
assertTrue(canonical.hasNonEmptyVersion());
|
||||||
|
String alternativeVer = "1.0";
|
||||||
|
String actualVer = canonical.getVersionOr(alternativeVer);
|
||||||
|
assertEquals(expectedVersion, actualVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1428,25 +1428,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String versionFromCanonical(String system) {
|
|
||||||
if (system == null) {
|
|
||||||
return null;
|
|
||||||
} else if (system.contains("|")) {
|
|
||||||
return system.substring(0, system.indexOf("|"));
|
|
||||||
} else {
|
|
||||||
return system;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String systemFromCanonical(String system) {
|
|
||||||
if (system == null) {
|
|
||||||
return null;
|
|
||||||
} else if (system.contains("|")) {
|
|
||||||
return system.substring(system.indexOf("|")+1);
|
|
||||||
} else {
|
|
||||||
return system;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource loadContainedResource(List<ValidationMessage> errors, String path, Element resource, String id, Class<? extends Resource> class1) throws FHIRException {
|
public Resource loadContainedResource(List<ValidationMessage> errors, String path, Element resource, String id, Class<? extends Resource> class1) throws FHIRException {
|
||||||
|
|
|
@ -1456,9 +1456,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
timeTracker.tx(t, "vc "+cc.toString());
|
timeTracker.tx(t, "vc "+cc.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (CheckCodeOnServerException e) {
|
||||||
if (STACK_TRACE) e.printStackTrace();
|
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getMessage());
|
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (binding.hasValueSet()) {
|
} else if (binding.hasValueSet()) {
|
||||||
|
@ -1469,6 +1469,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!noTerminologyChecks && theElementCntext != null && !checked) { // no binding check, so we just check the CodeableConcept generally
|
if (!noTerminologyChecks && theElementCntext != null && !checked) { // no binding check, so we just check the CodeableConcept generally
|
||||||
|
try {
|
||||||
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(element);
|
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(element);
|
||||||
if (cc.hasCoding()) {
|
if (cc.hasCoding()) {
|
||||||
long t = System.nanoTime();
|
long t = System.nanoTime();
|
||||||
|
@ -1476,6 +1477,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, false, null));
|
bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, false, null));
|
||||||
timeTracker.tx(t, "vc " + cc.toString());
|
timeTracker.tx(t, "vc " + cc.toString());
|
||||||
}
|
}
|
||||||
|
} catch (CheckCodeOnServerException e) {
|
||||||
|
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||||
|
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return checkDisp;
|
return checkDisp;
|
||||||
}
|
}
|
||||||
|
@ -1502,8 +1507,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
if (vr != null) {
|
if (vr != null) {
|
||||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||||
if (!iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-in-vs") &&
|
if (!iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-in-vs")
|
||||||
!iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs")
|
&& !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs")
|
||||||
&& !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) {
|
&& !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) {
|
||||||
OperationOutcomeIssueComponent i = iss.copy();
|
OperationOutcomeIssueComponent i = iss.copy();
|
||||||
if (notFoundLevel != null && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
|
if (notFoundLevel != null && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
|
||||||
|
@ -1653,9 +1658,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
timeTracker.tx(t, DataRenderer.display(context, cc));
|
timeTracker.tx(t, DataRenderer.display(context, cc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (CheckCodeOnServerException e) {
|
||||||
if (STACK_TRACE) e.printStackTrace();
|
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getMessage());
|
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage());
|
||||||
}
|
}
|
||||||
// special case: if the logical model has both CodeableConcept and Coding mappings, we'll also check the first coding.
|
// special case: if the logical model has both CodeableConcept and Coding mappings, we'll also check the first coding.
|
||||||
if (getMapping("http://hl7.org/fhir/terminology-pattern", logical, logical.getSnapshot().getElementFirstRep()).contains("Coding")) {
|
if (getMapping("http://hl7.org/fhir/terminology-pattern", logical, logical.getSnapshot().getElementFirstRep()).contains("Coding")) {
|
||||||
|
@ -1861,9 +1866,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
else
|
else
|
||||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_8, describeReference(maxVSUrl, valueset), ccSummary(cc)) && ok;
|
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_8, describeReference(maxVSUrl, valueset), ccSummary(cc)) && ok;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (CheckCodeOnServerException e) {
|
||||||
if (STACK_TRACE) e.printStackTrace();
|
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT_MAX, e.getMessage());
|
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT_MAX, e.getCause().getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -7474,6 +7479,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), vs, context.validateCode(options, value, vs)), new CodeType(value));
|
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), vs, context.validateCode(options, value, vs)), new CodeType(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class CheckCodeOnServerException extends Exception {
|
||||||
|
public CheckCodeOnServerException(Exception e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// no delay on this one?
|
// no delay on this one?
|
||||||
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String version, String display, boolean checkDisplay) {
|
public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String version, String display, boolean checkDisplay) {
|
||||||
|
@ -7490,9 +7500,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), c, valueset)), c);
|
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), c, valueset)), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc) {
|
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc) throws CheckCodeOnServerException {
|
||||||
codingObserver.seeCode(stack, cc);
|
codingObserver.seeCode(stack, cc);
|
||||||
|
try {
|
||||||
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset)), cc);
|
return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset)), cc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CheckCodeOnServerException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValidationResult filterOutSpecials(String path, ValueSet vs, ValidationResult vr) {
|
private ValidationResult filterOutSpecials(String path, ValueSet vs, ValidationResult vr) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
|
import org.hl7.fhir.utilities.CanonicalPair;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.VersionUtilities;
|
import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
|
@ -620,7 +621,8 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
private boolean validateSupplementConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String supp, ValidationOptions options) {
|
private boolean validateSupplementConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String supp, ValidationOptions options) {
|
||||||
String code = concept.getChildValue("code");
|
String code = concept.getChildValue("code");
|
||||||
if (!Utilities.noString(code)) {
|
if (!Utilities.noString(code)) {
|
||||||
org.hl7.fhir.r5.terminologies.utilities.ValidationResult res = context.validateCode(options, systemFromCanonical(supp), versionFromCanonical(supp), code, null);
|
var canonical = new CanonicalPair(supp);
|
||||||
|
org.hl7.fhir.r5.terminologies.utilities.ValidationResult res = context.validateCode(options, canonical.getUrl(), canonical.getVersion(), code, null);
|
||||||
return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code);
|
return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package org.hl7.fhir.validation;
|
package org.hl7.fhir.validation;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -10,6 +14,7 @@ import org.hl7.fhir.r5.formats.XmlParser;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||||
import org.hl7.fhir.utilities.FhirPublication;
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.settings.FhirSettings;
|
import org.hl7.fhir.utilities.settings.FhirSettings;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||||
|
@ -25,7 +30,7 @@ public class ResourceValidationTests {
|
||||||
private static InstanceValidator val;
|
private static InstanceValidator val;
|
||||||
|
|
||||||
|
|
||||||
private void runTest(String filename) throws IOException, FileNotFoundException, Exception {
|
private List<ValidationMessage> runTest(String filename) throws IOException, FileNotFoundException, Exception {
|
||||||
TestingUtilities.injectCorePackageLoader();
|
TestingUtilities.injectCorePackageLoader();
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
ctxt = TestingUtilities.getSharedWorkerContext();
|
ctxt = TestingUtilities.getSharedWorkerContext();
|
||||||
|
@ -37,6 +42,7 @@ public class ResourceValidationTests {
|
||||||
Resource res = (Resource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", filename));
|
Resource res = (Resource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", filename));
|
||||||
val.validate(val, errors, res);
|
val.validate(val, errors, res);
|
||||||
Assertions.assertNotNull(errors);
|
Assertions.assertNotNull(errors);
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,4 +129,26 @@ public class ResourceValidationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCodesystemSupplementsVersion() throws Exception {
|
||||||
|
List<ValidationMessage> errors = runTest("codesystem-example-supplement-version.xml");
|
||||||
|
assertNoErrors(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void assertNoErrors(List<ValidationMessage> errors) {
|
||||||
|
List<String> errorMessages = new ArrayList<>();
|
||||||
|
for(ValidationMessage message : errors) {
|
||||||
|
// we will skip the message that WG citation is needed
|
||||||
|
if(I18nConstants.VALIDATION_HL7_WG_NEEDED.equals(message.getMessageId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(message.getLevel().isError()) {
|
||||||
|
errorMessages.add(message.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertThat("No error message expected in validation outcome.", errorMessages, is(empty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue