Merge pull request #1281 from hapifhir/gg-202304-obligation-profiles

Gg 202304 obligation profiles
This commit is contained in:
Grahame Grieve 2023-05-29 03:16:31 +03:00 committed by GitHub
commit f04d8fc5a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 616 additions and 45 deletions

View File

@ -17,7 +17,7 @@ public class OIDBasedValueSetImporter {
protected void init() throws FHIRException, IOException { protected void init() throws FHIRException, IOException {
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER); FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER);
NpmPackage npm = pcm.loadPackage("hl7.fhir.r5.core", "current"); NpmPackage npm = pcm.loadPackage("hl7.fhir.r5.core", "5.0.0");
SimpleWorkerContext context = new SimpleWorkerContext.SimpleWorkerContextBuilder().withAllowLoadingDuplicates(true).fromPackage(npm); SimpleWorkerContext context = new SimpleWorkerContext.SimpleWorkerContextBuilder().withAllowLoadingDuplicates(true).fromPackage(npm);
context.loadFromPackage(pcm.loadPackage("hl7.terminology"), null); context.loadFromPackage(pcm.loadPackage("hl7.terminology"), null);
this.context = context; this.context = context;

View File

@ -304,7 +304,7 @@ public class ProfilePathProcessor {
if (profileUtilities.hasInnerDiffMatches(getDifferential(), currentBasePath, cursors.diffCursor, getDiffLimit(), cursors.base.getElement(), false)) { if (profileUtilities.hasInnerDiffMatches(getDifferential(), currentBasePath, cursors.diffCursor, getDiffLimit(), cursors.base.getElement(), false)) {
if (baseHasChildren(cursors.base, currentBase)) { // not a new type here if (baseHasChildren(cursors.base, currentBase)) { // not a new type here
if (cursors.diffCursor == 0) { if (cursors.diffCursor == 0) {
throw new DefinitionException("Error: The profile has slicing at the root, which is illegal"); throw new DefinitionException("Error: The profile has slicing at the root ('"+currentBase.getPath()+"'), which is illegal");
} else { } else {
throw new Error("This situation is not yet handled (constrain slicing to 1..1 and fix base slice for inline structure - please report issue to grahame@fhir.org along with a test case that reproduces this error (@ " + currentBasePath + " | " + currentBase.getPath() + ")"); throw new Error("This situation is not yet handled (constrain slicing to 1..1 and fix base slice for inline structure - please report issue to grahame@fhir.org along with a test case that reproduces this error (@ " + currentBasePath + " | " + currentBase.getPath() + ")");
} }
@ -766,6 +766,7 @@ public class ProfilePathProcessor {
outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource()));
profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl());
profileUtilities.updateConstraintSources(outcome, getSourceStructureDefinition().getUrl()); profileUtilities.updateConstraintSources(outcome, getSourceStructureDefinition().getUrl());
profileUtilities.updateFromObligationProfiles(outcome);
profileUtilities.updateURLs(url, webUrl, outcome); profileUtilities.updateURLs(url, webUrl, outcome);
profileUtilities.markDerived(outcome); profileUtilities.markDerived(outcome);
if (cursors.resultPathBase == null) if (cursors.resultPathBase == null)

View File

@ -61,6 +61,7 @@ import org.hl7.fhir.r5.model.Element;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBaseComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBaseComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionExampleComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionExampleComponent;
@ -349,6 +350,7 @@ public class ProfileUtilities extends TranslatingUtilities {
private AllowUnknownProfile allowUnknownProfile = AllowUnknownProfile.ALL_TYPES; private AllowUnknownProfile allowUnknownProfile = AllowUnknownProfile.ALL_TYPES;
private MappingMergeModeOption mappingMergeMode = MappingMergeModeOption.APPEND; private MappingMergeModeOption mappingMergeMode = MappingMergeModeOption.APPEND;
private boolean forPublication; private boolean forPublication;
private List<StructureDefinition> obligationProfiles = new ArrayList<>();
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) { public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
super(); super();
@ -627,6 +629,8 @@ public class ProfileUtilities extends TranslatingUtilities {
checkDifferentialBaseType(derived); checkDifferentialBaseType(derived);
copyInheritedExtensions(base, derived); copyInheritedExtensions(base, derived);
findInheritedObligationProfiles(derived);
// so we have two lists - the base list, and the differential list // so we have two lists - the base list, and the differential list
// the differential list is only allowed to include things that are in the base list, but // the differential list is only allowed to include things that are in the base list, but
// is allowed to include them multiple times - thereby slicing them // is allowed to include them multiple times - thereby slicing them
@ -853,6 +857,17 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
private void findInheritedObligationProfiles(StructureDefinition derived) {
for (Extension ext : derived.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_INHERITS)) {
StructureDefinition op = context.fetchResource(StructureDefinition.class, ext.getValueCanonicalType().primitiveValue());
if (op != null && ToolingExtensions.readBoolExtension(op, ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG)) {
if (derived.getBaseDefinition().equals(op.getBaseDefinition())) {
obligationProfiles.add(op);
}
}
}
}
private void handleError(String url, String msg) { private void handleError(String url, String msg) {
if (exception) if (exception)
throw new DefinitionException(msg); throw new DefinitionException(msg);
@ -2065,6 +2080,63 @@ public class ProfileUtilities extends TranslatingUtilities {
return true; return true;
} }
public void updateFromObligationProfiles(ElementDefinition base) {
List<ElementDefinition> obligationProfileElements = new ArrayList<>();
for (StructureDefinition sd : obligationProfiles) {
ElementDefinition ed = sd.getSnapshot().getElementById(base.getId());
if (ed != null) {
obligationProfileElements.add(ed);
}
}
for (ElementDefinition ed : obligationProfileElements) {
for (Extension ext : ed.getExtension()) {
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
base.getExtension().add(ext.copy());
}
}
}
boolean hasMustSupport = false;
for (ElementDefinition ed : obligationProfileElements) {
hasMustSupport = hasMustSupport || ed.hasMustSupportElement();
}
if (hasMustSupport) {
for (ElementDefinition ed : obligationProfileElements) {
mergeExtensions(base.getMustSupportElement(), ed.getMustSupportElement());
if (ed.getMustSupport()) {
base.setMustSupport(true);
}
}
}
boolean hasBinding = false;
for (ElementDefinition ed : obligationProfileElements) {
hasBinding = hasBinding || ed.hasBinding();
}
if (hasBinding) {
ElementDefinitionBindingComponent binding = base.getBinding();
for (ElementDefinition ed : obligationProfileElements) {
for (Extension ext : ed.getBinding().getExtension()) {
if (ToolingExtensions.EXT_BINDING_ADDITIONAL.equals(ext.getUrl())) {
String p = ext.getExtensionString("purpose");
if (!Utilities.existsInList(p, "maximum", "required", "extensible")) {
if (!binding.hasExtension(ext)) {
binding.getExtension().add(ext.copy());
}
}
}
}
for (ElementDefinitionBindingAdditionalComponent ab : ed.getBinding().getAdditional()) {
if (!Utilities.existsInList(ab.getPurpose().toCode(), "maximum", "required", "extensible")) {
if (!binding.hasAdditional(ab)) {
binding.getAdditional().add(ab.copy());
}
}
}
}
}
}
protected void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD, StructureDefinition derivedSrc) throws DefinitionException, FHIRException { protected void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD, StructureDefinition derivedSrc) throws DefinitionException, FHIRException {
source.setUserData(UD_GENERATED_IN_SNAPSHOT, dest); source.setUserData(UD_GENERATED_IN_SNAPSHOT, dest);
// we start with a clone of the base profile ('dest') and we copy from the profile ('source') // we start with a clone of the base profile ('dest') and we copy from the profile ('source')
@ -2073,13 +2145,31 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition derived = source; ElementDefinition derived = source;
derived.setUserData(UD_DERIVATION_POINTER, base); derived.setUserData(UD_DERIVATION_POINTER, base);
boolean isExtension = checkExtensionDoco(base); boolean isExtension = checkExtensionDoco(base);
List<ElementDefinition> obligationProfileElements = new ArrayList<>();
for (StructureDefinition sd : obligationProfiles) {
ElementDefinition ed = sd.getSnapshot().getElementById(base.getId());
if (ed != null) {
obligationProfileElements.add(ed);
}
}
for (Extension ext : source.getExtension()) { for (Extension ext : source.getExtension()) {
if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) { if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) {
dest.getExtension().add(ext.copy()); dest.getExtension().add(ext.copy());
} }
} }
for (Extension ext : source.getExtension()) {
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
dest.getExtension().add(ext.copy());
}
}
for (ElementDefinition ed : obligationProfileElements) {
for (Extension ext : ed.getExtension()) {
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
dest.getExtension().add(ext.copy());
}
}
}
// Before applying changes, apply them to what's in the profile // Before applying changes, apply them to what's in the profile
StructureDefinition profile = null; StructureDefinition profile = null;
if (base.hasSliceName()) { if (base.hasSliceName()) {
@ -2282,12 +2372,23 @@ public class ProfileUtilities extends TranslatingUtilities {
// todo: what to do about conditions? // todo: what to do about conditions?
// condition : id 0..* // condition : id 0..*
if (derived.hasMustSupportElement()) { boolean hasMustSupport = derived.hasMustSupportElement();
if (!(base.hasMustSupportElement() && Base.compareDeep(derived.getMustSupportElement(), base.getMustSupportElement(), false))) { for (ElementDefinition ed : obligationProfileElements) {
hasMustSupport = hasMustSupport || ed.hasMustSupportElement();
}
if (hasMustSupport) {
BooleanType mse = derived.getMustSupportElement().copy();
for (ElementDefinition ed : obligationProfileElements) {
mergeExtensions(mse, ed.getMustSupportElement());
if (ed.getMustSupport()) {
mse.setValue(true);
}
}
if (!(base.hasMustSupportElement() && Base.compareDeep(base.getMustSupportElement(), mse, false))) {
if (base.hasMustSupport() && base.getMustSupport() && !derived.getMustSupport()) { if (base.hasMustSupport() && base.getMustSupport() && !derived.getMustSupport()) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-support = false] when [must-support = true] in the base profile", ValidationMessage.IssueSeverity.ERROR)); messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-support = false] when [must-support = true] in the base profile", ValidationMessage.IssueSeverity.ERROR));
} }
base.setMustSupportElement(derived.getMustSupportElement().copy()); base.setMustSupportElement(mse);
} else if (trimDifferential) } else if (trimDifferential)
derived.setMustSupportElement(null); derived.setMustSupportElement(null);
else else
@ -2324,7 +2425,32 @@ public class ProfileUtilities extends TranslatingUtilities {
derived.getIsModifierReasonElement().setUserData(UD_DERIVATION_EQUALS, true); derived.getIsModifierReasonElement().setUserData(UD_DERIVATION_EQUALS, true);
} }
if (derived.hasBinding()) { boolean hasBinding = derived.hasBinding();
for (ElementDefinition ed : obligationProfileElements) {
hasBinding = hasBinding || ed.hasBinding();
}
if (hasBinding) {
ElementDefinitionBindingComponent binding = derived.getBinding();
for (ElementDefinition ed : obligationProfileElements) {
for (Extension ext : ed.getBinding().getExtension()) {
if (ToolingExtensions.EXT_BINDING_ADDITIONAL.equals(ext.getUrl())) {
String p = ext.getExtensionString("purpose");
if (!Utilities.existsInList(p, "maximum", "required", "extensible")) {
if (!binding.hasExtension(ext)) {
binding.getExtension().add(ext.copy());
}
}
}
}
for (ElementDefinitionBindingAdditionalComponent ab : ed.getBinding().getAdditional()) {
if (!Utilities.existsInList(ab.getPurpose().toCode(), "maximum", "required", "extensible")) {
if (binding.hasAdditional(ab)) {
binding.getAdditional().add(ab.copy());
}
}
}
}
if (!base.hasBinding() || !Base.compareDeep(derived.getBinding(), base.getBinding(), false)) { if (!base.hasBinding() || !Base.compareDeep(derived.getBinding(), base.getBinding(), false)) {
if (base.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && derived.getBinding().getStrength() != BindingStrength.REQUIRED) if (base.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && derived.getBinding().getStrength() != BindingStrength.REQUIRED)
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR)); messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR));
@ -2462,6 +2588,10 @@ public class ProfileUtilities extends TranslatingUtilities {
//updateURLs(url, webUrl, dest); //updateURLs(url, webUrl, dest);
} }
private void mergeExtensions(Element tgt, Element src) {
tgt.getExtension().addAll(src.getExtension());
}
private void addMappings(List<ElementDefinitionMappingComponent> destination, List<ElementDefinitionMappingComponent> source) { private void addMappings(List<ElementDefinitionMappingComponent> destination, List<ElementDefinitionMappingComponent> source) {
for (ElementDefinitionMappingComponent s : source) { for (ElementDefinitionMappingComponent s : source) {
boolean found = false; boolean found = false;

View File

@ -322,6 +322,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
locator = other.locator; locator = other.locator;
userAgent = other.userAgent; userAgent = other.userAgent;
tcc.copy(other.tcc); tcc.copy(other.tcc);
cachingAllowed = other.cachingAllowed;
} }
} }
@ -1050,9 +1051,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
codeSystemsUsed.add(code.getSystem()); codeSystemsUsed.add(code.getSystem());
} }
final CacheToken cacheToken = txCache != null ? txCache.generateValidationToken(options, code, vs, expParameters) : null; final CacheToken cacheToken = cachingAllowed && txCache != null ? txCache.generateValidationToken(options, code, vs, expParameters) : null;
ValidationResult res = null; ValidationResult res = null;
if (txCache != null) { if (cachingAllowed && txCache != null) {
res = txCache.getValidation(cacheToken); res = txCache.getValidation(cacheToken);
} }
if (res != null) { if (res != null) {
@ -1072,7 +1073,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null);
if (!ValueSetUtilities.isServerSide(code.getSystem())) { if (!ValueSetUtilities.isServerSide(code.getSystem())) {
res = vsc.validateCode(path, code); res = vsc.validateCode(path, code);
if (txCache != null) { if (txCache != null && cachingAllowed) {
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT); txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
} }
return res; return res;
@ -1107,8 +1108,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (noTerminologyServer) { if (noTerminologyServer) {
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, issues); return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, issues);
} }
String csumm = txCache != null ? txCache.summary(code) : null; String csumm =cachingAllowed && txCache != null ? txCache.summary(code) : null;
if (txCache != null) { if (cachingAllowed && txCache != null) {
txLog("$validate "+csumm+" for "+ txCache.summary(vs)); txLog("$validate "+csumm+" for "+ txCache.summary(vs));
} else { } else {
txLog("$validate "+csumm+" before cache exists"); txLog("$validate "+csumm+" before cache exists");
@ -1123,7 +1124,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
res.setDiagnostics("Local Error: "+localError.trim()+". Server Error: "+res.getMessage()); res.setDiagnostics("Local Error: "+localError.trim()+". Server Error: "+res.getMessage());
} }
updateUnsupportedCodeSystems(res, code, codeKey); updateUnsupportedCodeSystems(res, code, codeKey);
if (txCache != null) { // we never cache unsupported code systems - we always keep trying (but only once per run) if (cachingAllowed && txCache != null) { // we never cache unsupported code systems - we always keep trying (but only once per run)
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT); txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT);
} }
return res; return res;
@ -1204,9 +1205,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
@Override @Override
public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs) { public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs) {
CacheToken cacheToken = txCache.generateValidationToken(options, code, vs, expParameters); CacheToken cacheToken = txCache.generateValidationToken(options, code, vs, expParameters);
ValidationResult res = txCache.getValidation(cacheToken); ValidationResult res = null;
if (res != null) { if (cachingAllowed) {
return res; res = txCache.getValidation(cacheToken);
if (res != null) {
return res;
}
} }
for (Coding c : code.getCoding()) { for (Coding c : code.getCoding()) {
if (c.hasSystem()) { if (c.hasSystem()) {
@ -1222,7 +1226,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
vsc.setUnknownSystems(unknownSystems); vsc.setUnknownSystems(unknownSystems);
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null);
res = vsc.validateCode("CodeableConcept", code); res = vsc.validateCode("CodeableConcept", code);
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT); if (cachingAllowed) {
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
}
return res; return res;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -1247,7 +1253,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} catch (Exception e) { } catch (Exception e) {
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()); res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId());
} }
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT); if (cachingAllowed) {
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT);
}
return res; return res;
} }
@ -1919,6 +1927,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected IWorkerContextManager.IPackageLoadingTracker packageTracker; protected IWorkerContextManager.IPackageLoadingTracker packageTracker;
private boolean forPublication; private boolean forPublication;
private boolean cachingAllowed = true;
@Override @Override
public Resource fetchResourceById(String type, String uri) { public Resource fetchResourceById(String type, String uri) {
@ -2478,4 +2487,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
forPublication = value; forPublication = value;
} }
public boolean isCachingAllowed() {
return cachingAllowed;
}
public void setCachingAllowed(boolean cachingAllowed) {
this.cachingAllowed = cachingAllowed;
}
} }

View File

@ -304,6 +304,17 @@ public interface IWorkerContext {
return this; return this;
} }
public String unknownSystems() {
if (unknownSystems == null) {
return null;
}
if (unknownSystems.size() == 1) {
return unknownSystems.iterator().next();
} else {
return String.join(",", unknownSystems);
}
}
} }
public class CodingValidationRequest { public class CodingValidationRequest {

View File

@ -441,8 +441,9 @@ public class XmlParser extends ParserBase {
parseChildren(npath, (org.w3c.dom.Element) child, n); parseChildren(npath, (org.w3c.dom.Element) child, n);
} }
} }
} else } else {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName(), path), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName(), path), IssueSeverity.ERROR);
}
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){ } else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) { } else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {

View File

@ -457,6 +457,17 @@ public abstract class Element extends Base implements IBaseHasExtensions, IBaseE
ToolingExtensions.setStandardsStatus(this, status, null); ToolingExtensions.setStandardsStatus(this, status, null);
} }
public boolean hasExtension(Extension ext) {
if (hasExtension()) {
for (Extension t : getExtension()) {
if (Base.compareDeep(t, ext, false)) {
return true;
}
}
}
return false;
}
// end addition // end addition
} }

View File

@ -4919,6 +4919,17 @@ public boolean hasTarget() {
} }
public boolean hasAdditional(ElementDefinitionBindingAdditionalComponent ab) {
if (hasAdditional()) {
for (ElementDefinitionBindingAdditionalComponent t : getAdditional()) {
if (Base.compareDeep(t, ab, false)) {
return true;
}
}
}
return false;
}
} }
@Block() @Block()

View File

@ -385,5 +385,21 @@ public class ValueSetUtilities {
return code; return code;
} }
public static int countExpansion(ValueSet valueset) {
int i = valueset.getExpansion().getContains().size();
for (ValueSetExpansionContainsComponent t : valueset.getExpansion().getContains()) {
i = i + countExpansion(t);
}
return i;
}
private static int countExpansion(ValueSetExpansionContainsComponent c) {
int i = c.getContains().size();
for (ValueSetExpansionContainsComponent t : c.getContains()) {
i = i + countExpansion(t);
}
return i;
}
} }

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass; import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
/** /**
@ -74,4 +75,10 @@ public class ValueSetExpansionOutcome {
public boolean isOk() { public boolean isOk() {
return (allErrors.isEmpty() || (allErrors.size() == 1 && allErrors.get(0) == null)) && error == null; return (allErrors.isEmpty() || (allErrors.size() == 1 && allErrors.get(0) == null)) && error == null;
} }
public int count() {
if (valueset == null) {
return 0;
}
return ValueSetUtilities.countExpansion(valueset);
}
} }

View File

@ -493,6 +493,7 @@ public class ValueSetValidator {
res.getIssues().addAll(makeIssue(IssueSeverity.WARNING, IssueType.NOTFOUND, path, m)); res.getIssues().addAll(makeIssue(IssueSeverity.WARNING, IssueType.NOTFOUND, path, m));
res.setUnknownSystems(unknownSystems); res.setUnknownSystems(unknownSystems);
res.setSeverity(IssueSeverity.ERROR); // back patching for display logic issue res.setSeverity(IssueSeverity.ERROR); // back patching for display logic issue
res.setErrorClass(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
} else if (!inExpansion && !inInclude) { } else if (!inExpansion && !inInclude) {
// if (!info.getIssues().isEmpty()) { // if (!info.getIssues().isEmpty()) {
// res.setMessage("Not in value set "+valueset.getUrl()+": "+info.summary()).setSeverity(IssueSeverity.ERROR); // res.setMessage("Not in value set "+valueset.getUrl()+": "+info.summary()).setSeverity(IssueSeverity.ERROR);

View File

@ -1067,4 +1067,7 @@ public class ToolingExtensions {
return res; return res;
} }
public static final String EXT_OBLIGATION_PROFILE_FLAG = "http://hl7.org/fhir/tools/StructureDefinition/obligation-profile";
public static final String EXT_OBLIGATION_INHERITS = "http://hl7.org/fhir/tools/StructureDefinition/inherit-obligations";
} }

View File

@ -439,6 +439,7 @@ public class I18nConstants {
public static final String TERMINOLOGY_TX_NOVALID_13 = "Terminology_TX_NoValid_13"; public static final String TERMINOLOGY_TX_NOVALID_13 = "Terminology_TX_NoValid_13";
public static final String TERMINOLOGY_TX_NOVALID_14 = "Terminology_TX_NoValid_14"; public static final String TERMINOLOGY_TX_NOVALID_14 = "Terminology_TX_NoValid_14";
public static final String TERMINOLOGY_TX_NOVALID_15 = "Terminology_TX_NoValid_15"; public static final String TERMINOLOGY_TX_NOVALID_15 = "Terminology_TX_NoValid_15";
public static final String TERMINOLOGY_TX_NOVALID_15A = "Terminology_TX_NoValid_15A";
public static final String TERMINOLOGY_TX_NOVALID_16 = "Terminology_TX_NoValid_16"; public static final String TERMINOLOGY_TX_NOVALID_16 = "Terminology_TX_NoValid_16";
public static final String TERMINOLOGY_TX_NOVALID_17 = "Terminology_TX_NoValid_17"; public static final String TERMINOLOGY_TX_NOVALID_17 = "Terminology_TX_NoValid_17";
public static final String TERMINOLOGY_TX_NOVALID_18 = "Terminology_TX_NoValid_18"; public static final String TERMINOLOGY_TX_NOVALID_18 = "Terminology_TX_NoValid_18";
@ -870,6 +871,19 @@ public class I18nConstants {
public static final String ATTEMPT_TO_CHANGE_SLICING = "ATTEMPT_TO_CHANGE_SLICING"; public static final String ATTEMPT_TO_CHANGE_SLICING = "ATTEMPT_TO_CHANGE_SLICING";
public static final String REPEAT_SLICING_IGNORED = "REPEAT_SLICING_IGNORED"; public static final String REPEAT_SLICING_IGNORED = "REPEAT_SLICING_IGNORED";
public static final String SD_ELEMENT_NOT_IN_CONSTRAINT = "SD_ELEMENT_NOT_IN_CONSTRAINT"; public static final String SD_ELEMENT_NOT_IN_CONSTRAINT = "SD_ELEMENT_NOT_IN_CONSTRAINT";
public static final String SD_OBGLIGATION_PROFILE_UKNOWN = "SD_OBGLIGATION_PROFILE_UKNOWN";
public static final String SD_OBGLIGATION_PROFILE_DERIVATION = "SD_OBGLIGATION_PROFILE_DERIVATION";
public static final String SD_OBGLIGATION_PROFILE_UNMATCHED = "SD_OBGLIGATION_PROFILE_UNMATCHED";
public static final String SD_OBGLIGATION_PROFILE_PATH_WRONG = "SD_OBGLIGATION_PROFILE_PATH_WRONG";
public static final String SD_OBGLIGATION_PROFILE_ILLEGAL = "SD_OBGLIGATION_PROFILE_ILLEGAL";
public static final String SD_OBGLIGATION_PROFILE_ILLEGAL_ON_BINDING = "SD_OBGLIGATION_PROFILE_ILLEGAL_ON_BINDING";
public static final String SD_OBGLIGATION_PROFILE_INVALID_BINDING_CODE = "SD_OBGLIGATION_PROFILE_INVALID_BINDING_CODE";
public static final String SD_OBGLIGATION_PROFILE_INVALID_BINDING_STRENGTH = "SD_OBGLIGATION_PROFILE_INVALID_BINDING_STRENGTH";
public static final String SD_OBGLIGATION_PROFILE_ILLEGAL_BINDING = "SD_OBGLIGATION_PROFILE_ILLEGAL_BINDING";
public static final String SD_OBGLIGATION_INHERITS_PROFILE_NO_TARGET = "SD_OBGLIGATION_INHERITS_PROFILE_NO_TARGET";
public static final String SD_OBGLIGATION_INHERITS_PROFILE_TARGET_NOT_FOUND = "SD_OBGLIGATION_INHERITS_PROFILE_TARGET_NOT_FOUND";
public static final String SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_TYPE = "SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_TYPE";
public static final String SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_BASE = "SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_BASE";
} }

View File

@ -14,6 +14,10 @@ public class JsonNumber extends JsonPrimitive {
this.value = Integer.toString(value); this.value = Integer.toString(value);
} }
public JsonNumber(long value) {
this.value = Long.toString(value);
}
private JsonNumber() { private JsonNumber() {
} }

View File

@ -66,6 +66,13 @@ public class JsonObject extends JsonElement {
return add(name, new JsonNumber(value)); return add(name, new JsonNumber(value));
} }
public JsonObject add(String name, long value) throws JsonException {
check(name != null, "Name is null");
return add(name, new JsonNumber(value));
}
public JsonObject set(String name, JsonElement value) throws JsonException { public JsonObject set(String name, JsonElement value) throws JsonException {
check(name != null, "Name is null"); check(name != null, "Name is null");
check(value != null, "Value is null"); check(value != null, "Value is null");

View File

@ -0,0 +1,76 @@
package org.hl7.fhir.utilities.xml;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class XmlEscaper {
private InputStream source;
private OutputStream target;
protected XmlEscaper(InputStream source, OutputStream target) {
super();
this.source = source;
this.target = target;
}
public static void convert(InputStream source, OutputStream target) throws IOException {
XmlEscaper self = new XmlEscaper(source, target);
self.process();
}
public static void convert(String source, String target) throws IOException {
convertAndClose(new FileInputStream(source), new FileOutputStream(target));
}
public static void convertAndClose(InputStream source, OutputStream target) throws IOException {
XmlEscaper self = new XmlEscaper(source, target);
self.process();
source.close();
target.close();
}
public InputStream getSource() {
return source;
}
public void setSource(InputStream source) {
this.source = source;
}
public OutputStream getTarget() {
return target;
}
public void setTarget(OutputStream target) {
this.target = target;
}
public void process() throws IOException {
BufferedReader buffer = new BufferedReader(new InputStreamReader(source));
int i = 0;
while ((i = buffer.read()) != -1) {
char c = (char) i;
if (c == '<')
write("&lt;");
else if (c == '>')
write("&gt;");
else if (c == '&')
write("&amp;");
else if (c == '"')
write("&quot;");
else
target.write((byte) i);
}
}
private void write(String s) throws IOException {
target.write(s.getBytes(StandardCharsets.UTF_8));
}
}

View File

@ -139,7 +139,7 @@ Terminology_PassThrough_TX_Message = {0} for ''{1}#{2}''
Terminology_TX_Binding_CantCheck = Binding by URI reference cannot be checked Terminology_TX_Binding_CantCheck = Binding by URI reference cannot be checked
Terminology_TX_Binding_Missing = Binding for CodeableConcept {0} missing Terminology_TX_Binding_Missing = Binding for CodeableConcept {0} missing
Terminology_TX_Binding_Missing2 = Binding for Coding {0} missing Terminology_TX_Binding_Missing2 = Binding for Coding {0} missing
Terminology_TX_Binding_NoServer = The value provided could not be validated in the absence of a terminology server Terminology_TX_Binding_NoServer = The value provided ([{0}]) could not be validated in the absence of a terminology server
Terminology_TX_Binding_NoSource = Binding for path {0} has no source, so can''t be checked Terminology_TX_Binding_NoSource = Binding for path {0} has no source, so can''t be checked
Terminology_TX_Binding_NoSource2 = Binding has no source, so can''t be checked Terminology_TX_Binding_NoSource2 = Binding has no source, so can''t be checked
Terminology_TX_Code_NotValid = Code {0} is not a valid code in code system {1} Terminology_TX_Code_NotValid = Code {0} is not a valid code in code system {1}
@ -168,6 +168,7 @@ Terminology_TX_NoValid_12 = The Coding provided ({2}) is not in the value set {0
Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable). {1} Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable). {1}
Terminology_TX_NoValid_14 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set. {1} Terminology_TX_NoValid_14 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set. {1}
Terminology_TX_NoValid_15 = The value provided (''{0}'') could not be validated in the absence of a terminology server Terminology_TX_NoValid_15 = The value provided (''{0}'') could not be validated in the absence of a terminology server
Terminology_TX_NoValid_15A = The value provided (''{0}'') could not be validated because the code system {1} is not known
Terminology_TX_NoValid_16 = The value provided (''{0}'') is not in the value set {1}, and a code is required from this value set){2} Terminology_TX_NoValid_16 = The value provided (''{0}'') is not in the value set {1}, and a code is required from this value set){2}
Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1}, and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) {2} Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1}, and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) {2}
Terminology_TX_NoValid_18 = The value provided (''{0}'') is not in the value set {1}, and a code is recommended to come from this value set){2} Terminology_TX_NoValid_18 = The value provided (''{0}'') is not in the value set {1}, and a code is recommended to come from this value set){2}
@ -178,7 +179,7 @@ Terminology_TX_NoValid_5 = The Coding provided ({2}) is not in the value set {0}
Terminology_TX_NoValid_6 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set {1} Terminology_TX_NoValid_6 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set {1}
Terminology_TX_NoValid_7 = None of the codes provided could be validated against the maximum value set {0}, (error = {2}) Terminology_TX_NoValid_7 = None of the codes provided could be validated against the maximum value set {0}, (error = {2})
Terminology_TX_NoValid_8 = None of the codes provided are in the maximum value set {0}, and a code from this value set is required) (codes = {1}) Terminology_TX_NoValid_8 = None of the codes provided are in the maximum value set {0}, and a code from this value set is required) (codes = {1})
Terminology_TX_NoValid_9 = The code provided could not be validated against the maximum value set {0}, (error = {1}) Terminology_TX_NoValid_9 = The code provided ({2}) could not be validated against the maximum value set {0}, (error = {1})
Terminology_TX_System_Invalid = Invalid System URI: {0} Terminology_TX_System_Invalid = Invalid System URI: {0}
Terminology_TX_System_NotKnown = Code System URI ''{0}'' is unknown so the code cannot be validated Terminology_TX_System_NotKnown = Code System URI ''{0}'' is unknown so the code cannot be validated
Terminology_TX_System_Relative = Coding.system must be an absolute reference, not a local reference Terminology_TX_System_Relative = Coding.system must be an absolute reference, not a local reference
@ -560,8 +561,8 @@ SEARCHPARAMETER_BASE_WRONG = The resource type {1} is not listed as a base in th
SEARCHPARAMETER_TYPE_WRONG = The type {1} is different to the type {0} in the derivedFrom SearchParameter SEARCHPARAMETER_TYPE_WRONG = The type {1} is different to the type {0} in the derivedFrom SearchParameter
SEARCHPARAMETER_EXP_WRONG = The expression ''{2}'' is not compatible with the expression ''{1}'' in the derivedFrom SearchParameter {0}, and this likely indicates that the derivation relationship is not valid SEARCHPARAMETER_EXP_WRONG = The expression ''{2}'' is not compatible with the expression ''{1}'' in the derivedFrom SearchParameter {0}, and this likely indicates that the derivation relationship is not valid
VALUESET_NO_SYSTEM_WARNING = No System specified, so Concepts and Filters can't be checked VALUESET_NO_SYSTEM_WARNING = No System specified, so Concepts and Filters can't be checked
VALUESET_INCLUDE_INVALID_CONCEPT_CODE = The code {1} is not valid in the system {0} VALUESET_INCLUDE_INVALID_CONCEPT_CODE = The code ''{1}'' is not valid in the system {0}
VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = The code {2} is not valid in the system {0} version {1} VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = The code ''{2}'' is not valid in the system {0} version {1}
VALUESET_EXAMPLE_SYSTEM_HINT = Example System ''{0}'' specified, so Concepts and Filters can''t be checked VALUESET_EXAMPLE_SYSTEM_HINT = Example System ''{0}'' specified, so Concepts and Filters can''t be checked
VALUESET_EXAMPLE_SYSTEM_ERROR = Example System ''{0}'' specified, which is illegal. Concepts and Filters can''t be checked VALUESET_EXAMPLE_SYSTEM_ERROR = Example System ''{0}'' specified, which is illegal. Concepts and Filters can''t be checked
VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1}) VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
@ -924,3 +925,17 @@ ED_PATH_WRONG_TYPE_MATCH = The path must be ''{0}'' not ''{1}'' when the type li
ATTEMPT_TO_CHANGE_SLICING = The element at {0} defines the slicing {1} but then an element in the slicing {2} tries to redefine the slicing to {3} ATTEMPT_TO_CHANGE_SLICING = The element at {0} defines the slicing {1} but then an element in the slicing {2} tries to redefine the slicing to {3}
REPEAT_SLICING_IGNORED = The element at {0} defines the slicing but then an element in the slicing {2} repeats it, which is ignored REPEAT_SLICING_IGNORED = The element at {0} defines the slicing but then an element in the slicing {2} repeats it, which is ignored
SD_ELEMENT_NOT_IN_CONSTRAINT = The element definition for {1} has a property {0} which is not allowed in a profile SD_ELEMENT_NOT_IN_CONSTRAINT = The element definition for {1} has a property {0} which is not allowed in a profile
SD_OBGLIGATION_PROFILE_UKNOWN = The profile is marked as an obligation profile, but it's correctness cannot be checked since the base profile ''{0}'' is not known
SD_OBGLIGATION_PROFILE_DERIVATION = Only profiles that constrain another profile can be marked as an obligation profile
SD_OBGLIGATION_PROFILE_UNMATCHED = The element ''{0}'' has no equivalent in the profile ''{1}'' on which this Obligation Profile is based
SD_OBGLIGATION_PROFILE_PATH_WRONG = The element ''{0}'' path value of ''{1}'' doesn't match the base path ''{2}''
SD_OBGLIGATION_PROFILE_ILLEGAL = The element ''{0}'' has a property ''{1}'' which is not allowed in Obligation profiles
SD_OBGLIGATION_PROFILE_ILLEGAL_ON_BINDING = The element ''{0}'' has a binding property ''{1}'' which is not allowed in Obligation profiles
SD_OBGLIGATION_PROFILE_ILLEGAL_BINDING = The element ''{0}'' has a binding when the base element does not, and this is not allowed in Obligation profiles
SD_OBGLIGATION_PROFILE_INVALID_BINDING_CODE = The element ''{0}'' has an additional binding purpose of ''{1}'' which is not allowed in Obligation profiles
SD_OBGLIGATION_PROFILE_INVALID_BINDING_STRENGTH =The element ''{0}'' has a different binding strength (''{1}'') from the base (''{2}'') which is not allowed in Obligation profiles
SD_OBGLIGATION_INHERITS_PROFILE_NO_TARGET = Unable to read a value from this extension
SD_OBGLIGATION_INHERITS_PROFILE_TARGET_NOT_FOUND = The profile ''{0}'' could not be found
SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_TYPE = The profile ''{0}'' is not marked as an obligation profile
SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_BASE = The profile ''{0}'' has a different base ''{1}'' from that expected ''{2}''

View File

@ -1507,7 +1507,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'"); timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
if (vr != null && !vr.isOk()) { if (vr != null && !vr.isOk()) {
if (vr.IsNoService()) if (vr.IsNoService())
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER); txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER, system+"#"+code);
else if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) { else if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
if (binding.getStrength() == BindingStrength.REQUIRED) if (binding.getStrength() == BindingStrength.REQUIRED)
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(binding.getValueSet(), valueset), vr.getMessage(), system+"#"+code); txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(binding.getValueSet(), valueset), vr.getMessage(), system+"#"+code);
@ -1680,7 +1680,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (!vr.isOk()) { if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset), vr.getMessage()); txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset), vr.getMessage(), c.getSystem()+"#"+c.getCode());
else else
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_10, describeReference(maxVSUrl, valueset), c.getSystem(), c.getCode()) && ok; ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_10, describeReference(maxVSUrl, valueset), c.getSystem(), c.getCode()) && ok;
} }
@ -1709,7 +1709,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
timeTracker.tx(t, "vc "+value); timeTracker.tx(t, "vc "+value);
if (!vr.isOk()) { if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset), vr.getMessage()); txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset), vr.getMessage(), value);
else { else {
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_11, describeReference(maxVSUrl, valueset), vr.getMessage()) && ok; ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_11, describeReference(maxVSUrl, valueset), vr.getMessage()) && ok;
} }
@ -1785,7 +1785,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (vr != null && !vr.isOk()) { if (vr != null && !vr.isOk()) {
if (vr.IsNoService()) if (vr.IsNoService())
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER); txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER, theSystem+"#"+theCode);
else if (vr.getErrorClass() != null && !vr.getErrorClass().isInfrastructure()) { else if (vr.getErrorClass() != null && !vr.getErrorClass().isInfrastructure()) {
if (binding.getStrength() == BindingStrength.REQUIRED) if (binding.getStrength() == BindingStrength.REQUIRED)
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(binding.getValueSet(), valueset), vr.getMessage(), theSystem+"#"+theCode) && ok; ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(binding.getValueSet(), valueset), vr.getMessage(), theSystem+"#"+theCode) && ok;
@ -3020,11 +3020,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
removeTrackedMessagesForLocation(errors, element, path); removeTrackedMessagesForLocation(errors, element, path);
} }
if (vr != null && !vr.isOk()) { if (vr != null && !vr.isOk()) {
if (vr.IsNoService()) if (vr.IsNoService()) {
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_15, value); txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_15, value);
else if (binding.getStrength() == BindingStrength.REQUIRED) } else if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_15A, value, vr.unknownSystems(), describeReference(binding.getValueSet()));
} else if (binding.getStrength() == BindingStrength.REQUIRED) {
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_16, value, describeReference(binding.getValueSet(), vs), getErrorMessage(vr.getMessage())) && ok; ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_16, value, describeReference(binding.getValueSet(), vs), getErrorMessage(vr.getMessage())) && ok;
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { } else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET)) if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET))
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), value, stack) && ok; ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), value, stack) && ok;
else if (!noExtensibleWarnings && !isOkExtension(value, vs)) else if (!noExtensibleWarnings && !isOkExtension(value, vs))

View File

@ -123,20 +123,174 @@ public class StructureDefinitionValidator extends BaseValidator {
I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok; I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok;
} }
} }
List<Element> differentials = src.getChildrenByName("differential");
List<Element> snapshots = src.getChildrenByName("snapshot");
boolean logical = "logical".equals(src.getNamedChildValue("kind"));
boolean constraint = "constraint".equals(src.getNamedChildValue("derivation"));
for (Element differential : differentials) {
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint) && ok;
}
for (Element snapshotE : snapshots) {
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint) && ok;
}
// obligation profile support
if (src.hasExtension(ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG)) {
Element ext = src.getExtension(ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG);
Element value = ext.getNamedChild("value");
if (value != null && "true".equals(value.primitiveValue())) {
if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), "constraint".equals(src.getNamedChildValue("derivation")), I18nConstants.SD_OBGLIGATION_PROFILE_DERIVATION)) {
if (warning(errors, "2023-05-27", IssueType.NOTFOUND, stack.getLiteralPath(), base != null, I18nConstants.SD_OBGLIGATION_PROFILE_UKNOWN, src.getNamedChildValue("baseDefinition"))) {
for (Element differential : differentials) {
ok = validateObligationProfile(errors, differential, stack.push(differential, -1, null, null), base) && ok;
}
}
}
}
}
List<Element> extensions = src.getChildren("extension");
int c = 0;
for (Element extension : extensions) {
if (ToolingExtensions.EXT_OBLIGATION_INHERITS.equals(extension.getNamedChildValue("url"))) {
ok = validateInheritsObligationProfile(errors, extension, stack.push(extension, c, null, null), src) && ok;
}
c++;
}
} catch (Exception e) { } catch (Exception e) {
rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage()); rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
ok = false; ok = false;
} }
return ok;
}
List<Element> differentials = src.getChildrenByName("differential");
List<Element> snapshots = src.getChildrenByName("snapshot"); private boolean validateInheritsObligationProfile(List<ValidationMessage> errors, Element extension, NodeStack stack, Element src) {
boolean logical = "logical".equals(src.getNamedChildValue("kind")); String tgt = extension.getNamedChildValue("value");
boolean constraint = "constraint".equals(src.getNamedChildValue("derivation")); if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), tgt != null,
for (Element differential : differentials) { I18nConstants.SD_OBGLIGATION_INHERITS_PROFILE_NO_TARGET)) {
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint) && ok; StructureDefinition sd = context.fetchResource(StructureDefinition.class, tgt);
if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), src != null,
I18nConstants.SD_OBGLIGATION_INHERITS_PROFILE_TARGET_NOT_FOUND, tgt)) {
if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), ToolingExtensions.readBoolExtension(sd, ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG),
I18nConstants.SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_TYPE, tgt)) {
String base = src.getNamedChildValue("baseDefinition");
if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), base != null && base.equals(sd.getBaseDefinition()),
I18nConstants.SD_OBGLIGATION_INHERITS_PROFILE_NOT_RIGHT_BASE, tgt, sd.getBaseDefinition(), base)) {
return true;
}
}
}
} }
for (Element snapshot : snapshots) { return false;
ok = validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true, sd, typeName, logical, constraint) && ok; }
private boolean validateObligationProfile(List<ValidationMessage> errors, Element elementList, NodeStack stack, StructureDefinition base) {
boolean ok = true;
List<Element> elements = elementList.getChildrenByName("element");
int cc = 0;
for (Element element : elements) {
ok = validateObligationProfileElement(errors, element, stack.push(element, cc, null, null), base) && ok;
cc++;
}
return ok;
}
private boolean validateObligationProfileElement(List<ValidationMessage> errors, Element element, NodeStack push, StructureDefinition base) {
// rules: it must exist in the base snapshot
// it must only add must-support, obligations and extra bindings
String id = element.getNamedChildValue("id");
ElementDefinition bd = base.getSnapshot().getElementById(id);
if (rule(errors, "2023-05-27", IssueType.INVALID, push.getLiteralPath(), bd != null, I18nConstants.SD_OBGLIGATION_PROFILE_UNMATCHED, id, base.getVersionedUrl())) {
boolean ok = true;
String name = null;
int c = 0;
for (Element child : element.getChildren()) {
if (child.getName().equals(name)) {
c++;
} else {
name = child.getName();
c = 0;
}
NodeStack stack = push.push(child, c, null, null);
if (child.getName().equals("extension")) {
String url = child.getNamedChildValue("url");
if ("http://hl7.org/fhir/tools/StructureDefinition/obligation".equals(url)) {
// this is ok, and it doesn't matter what's in the obligation
} else {
ok = false;
rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), false,
I18nConstants.SD_OBGLIGATION_PROFILE_ILLEGAL, id, child.getName()+"#"+url);
}
} else if (child.getName().equals("mustSupport")) {
// this is ok, and there's nothing to check
} else if (child.getName().equals("id")) {
// this is ok (it must have this), and there's nothing to check
} else if (child.getName().equals("binding")) {
if (rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), bd.hasBinding(),
I18nConstants.SD_OBGLIGATION_PROFILE_ILLEGAL_BINDING, id)) {
ok = validateObligationProfileElementBinding(errors, child, stack, id, bd) && ok;
} else {
ok = false;
}
} else if (child.getName().equals("path")) {
ok = rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), child.primitiveValue().equals(bd.getPath()),
I18nConstants.SD_OBGLIGATION_PROFILE_PATH_WRONG, id, child.primitiveValue(), bd.getPath()) && ok;
} else {
ok = false;
rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), false,
I18nConstants.SD_OBGLIGATION_PROFILE_ILLEGAL, id, child.getName());
}
}
return ok;
} else {
return false;
}
}
private boolean validateObligationProfileElementBinding(List<ValidationMessage> errors, Element element, NodeStack nstack, String id, ElementDefinition bd) {
// rules can only have additional bindings
boolean ok = true;
String name = null;
int c = 0;
for (Element child : element.getChildren()) {
if (child.getName().equals(name)) {
c++;
} else {
name = child.getName();
c = 0;
}
NodeStack stack = nstack.push(child, c, null, null);
if (child.getName().equals("extension")) {
String url = child.getNamedChildValue("url");
if ("http://hl7.org/fhir/tools/StructureDefinition/additional-binding".equals(url) && !VersionUtilities.isR5Plus(context.getVersion())) {
Element purpose = child.getExtension("purpose");
if (purpose != null) { // should be an error elsewhere
String code = purpose.getNamedChildValue("value");
ok = rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), !Utilities.existsInList(code, "maximum", "required", "extensible"),
I18nConstants.SD_OBGLIGATION_PROFILE_INVALID_BINDING_CODE, id, code) && ok;
}
} else {
ok = false;
rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), false,
I18nConstants.SD_OBGLIGATION_PROFILE_ILLEGAL, id, child.getName()+"#"+url);
}
} else if (child.getName().equals("additional") && VersionUtilities.isR5Plus(context.getVersion())) {
String code = child.getNamedChildValue("purpose");
ok = rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), !Utilities.existsInList(code, "maximum", "required", "extensible"),
I18nConstants.SD_OBGLIGATION_PROFILE_INVALID_BINDING_CODE, id, code) && ok;
} else if (child.getName().equals("strength")) {
// this has to be repeated, and has to be the same as the derivation
String strengthBase = bd.getBinding().getStrengthElement().asStringValue();
String strengthDerived = child.primitiveValue();
ok = rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), strengthBase != null && strengthBase.equals(strengthDerived),
I18nConstants.SD_OBGLIGATION_PROFILE_INVALID_BINDING_STRENGTH, id, strengthDerived, strengthBase) && ok;
} else {
ok = false;
rule(errors, "2023-05-27", IssueType.INVALID, stack.getLiteralPath(), false,
I18nConstants.SD_OBGLIGATION_PROFILE_ILLEGAL_ON_BINDING, id, child.getName());
}
} }
return ok; return ok;
} }
@ -194,7 +348,6 @@ public class StructureDefinitionValidator extends BaseValidator {
rule(errors, "2022-11-02", IssueType.NOTFOUND, stack.getLiteralPath(), typeName == null || path == null || path.equals(typeName) || path.startsWith(typeName+"."), I18nConstants.SD_PATH_TYPE_MISMATCH, typeName, path); rule(errors, "2022-11-02", IssueType.NOTFOUND, stack.getLiteralPath(), typeName == null || path == null || path.equals(typeName) || path.startsWith(typeName+"."), I18nConstants.SD_PATH_TYPE_MISMATCH, typeName, path);
if (!snapshot) { if (!snapshot) {
rule(errors, "2023-01-17", IssueType.INVALID, stack.getLiteralPath(), path.contains(".") || !element.hasChild("slicing"), I18nConstants.SD_NO_SLICING_ON_ROOT, path); rule(errors, "2023-01-17", IssueType.INVALID, stack.getLiteralPath(), path.contains(".") || !element.hasChild("slicing"), I18nConstants.SD_NO_SLICING_ON_ROOT, path);
} }
rule(errors, "2023-05-22", IssueType.NOTFOUND, stack.getLiteralPath(), snapshot || !constraint || !element.hasChild("meaningWhenMissing") || meaningWhenMissingAllowed(element), I18nConstants.SD_ELEMENT_NOT_IN_CONSTRAINT, "meaningWhenMissing", path); rule(errors, "2023-05-22", IssueType.NOTFOUND, stack.getLiteralPath(), snapshot || !constraint || !element.hasChild("meaningWhenMissing") || meaningWhenMissingAllowed(element), I18nConstants.SD_ELEMENT_NOT_IN_CONSTRAINT, "meaningWhenMissing", path);

View File

@ -36,6 +36,7 @@ import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
@ -245,6 +246,13 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} else { } else {
val.setBaseOptions(val.getBaseOptions().withVersionFlexible(false)); val.setBaseOptions(val.getBaseOptions().withVersionFlexible(false));
} }
if (content.has("no-tx")) {
boolean notx = "true".equals(content.get("no-tx").getAsString());
((SimpleWorkerContext) val.getContext()).setCanRunWithoutTerminology(notx);
((SimpleWorkerContext) val.getContext()).setNoTerminologyServer(notx);
((SimpleWorkerContext) val.getContext()).setCachingAllowed(!notx);
}
if (content.has("packages")) { if (content.has("packages")) {
for (JsonElement e : content.getAsJsonArray("packages")) { for (JsonElement e : content.getAsJsonArray("packages")) {
String n = e.getAsString(); String n = e.getAsString();

View File

@ -1152,3 +1152,19 @@ v: {
"version" : "http://snomed.info/sct/900000000000207008/version/20230131" "version" : "http://snomed.info/sct/900000000000207008/version/20230131"
} }
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
{"code" : {
"code" : "kg"
}, "url": "http://fhir.de/ValueSet/VitalSignDE_Body_Weigth_UCUM", "version": "0.9.13", "langs":"[en]", "useServer":"true", "useClient":"true", "guessSystem":"true", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "kilogram",
"code" : "kg",
"system" : "http://unitsofmeasure.org",
"version" : "2.0.1"
}
-------------------------------------------------------------------------------------

View File

@ -3462,3 +3462,20 @@ v: {
"version" : "2.74" "version" : "2.74"
} }
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
{"code" : {
"system" : "http://loinc.org",
"code" : "29463-7"
}, "url": "http://fhir.de/ValueSet/VitalSignDE_Body_Weight_Loinc--0", "version": "0.9.13", "langs":"[en]", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"CHECK_MEMERSHIP_ONLY", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Body weight",
"code" : "29463-7",
"system" : "http://loinc.org",
"version" : "2.74"
}
-------------------------------------------------------------------------------------

View File

@ -2188,3 +2188,36 @@ v: {
"version" : "http://snomed.info/sct/900000000000207008/version/20210731" "version" : "http://snomed.info/sct/900000000000207008/version/20210731"
} }
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
{"code" : {
"system" : "http://snomed.info/sct",
"code" : "27113001"
}, "url": "https://fhir.kbv.de/ValueSet/KBV_VS_Base_Body_Weight_Snomed--0", "version": "1.2.1", "langs":"[en]", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"CHECK_MEMERSHIP_ONLY", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Body weight (observable entity)",
"code" : "27113001",
"system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20210731"
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://snomed.info/sct",
"code" : "27113001"
}, "url": "https://fhir.kbv.de/ValueSet/KBV_VS_Base_Body_Weight_Snomed--1", "version": "1.2.1", "langs":"[en]", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"CHECK_MEMERSHIP_ONLY", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"severity" : "error",
"error" : "The provided code http://snomed.info/sct#27113001 is not in the value set 'https://fhir.kbv.de/ValueSet/KBV_VS_Base_Body_Weight_Snomed--1|1.2.1' (from Tx-Server)",
"class" : "UNKNOWN"
}
-------------------------------------------------------------------------------------

View File

@ -436,3 +436,20 @@ v: {
"class" : "UNKNOWN" "class" : "UNKNOWN"
} }
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
{"code" : {
"system" : "http://unitsofmeasure.org",
"code" : "kg"
}, "url": "http://fhir.de/ValueSet/UcumVitalsCommonDE--0", "version": "0.9.13", "langs":"[en]", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"CHECK_MEMERSHIP_ONLY", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "kilogram",
"code" : "kg",
"system" : "http://unitsofmeasure.org",
"version" : "2.0.1"
}
-------------------------------------------------------------------------------------

View File

@ -19,7 +19,7 @@
<properties> <properties>
<hapi_fhir_version>6.4.1</hapi_fhir_version> <hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.3.7</validator_test_case_version> <validator_test_case_version>1.3.8-SNAPSHOT</validator_test_case_version>
<jackson_version>2.14.0</jackson_version> <jackson_version>2.14.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version> <junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version> <junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>