Merge branch 'master' into do-20240830-maven-compiler-update
This commit is contained in:
commit
4ab12ab39d
|
@ -1,18 +1,7 @@
|
|||
## Validator Changes
|
||||
|
||||
* Fix expression for con-3 properly (fix validation problem on some condition resources)
|
||||
* Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types
|
||||
* FHIRPath: Allow _ in constant names (per FHIRPath spec)
|
||||
* Fix value set rendering creating wrong references
|
||||
* Fix bug processing value set includes / excludes that are just value sets (no system value)
|
||||
* Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors
|
||||
* Improve message for when elements are out of order in profile differentials
|
||||
|
||||
* no changes
|
||||
|
||||
## Other code changes
|
||||
|
||||
* fix problem where profile rendering had spurious 'slices for' nodes everywhere
|
||||
* Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository
|
||||
* Fix problem generating value set spreadsheets
|
||||
* fix concurrent modification error processing language translations
|
||||
* Check for null fetcher processing ConceptMaps (#1728)
|
||||
* no changes
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
@ -1,5 +1,5 @@
|
|||
Locale,Coverage #,Coverage %
|
||||
de,831,41%
|
||||
de,831,40%
|
||||
es,714,35%
|
||||
ja,902,44%
|
||||
nl,1989,98%
|
||||
nl,1988,97%
|
||||
|
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public class Consent30_40 {
|
|||
tgt.setPolicyRule(new CodeableConcept(c));
|
||||
}
|
||||
if (src.hasSecurityLabel() || src.hasPeriod() || src.hasActor() || src.hasAction() || src.hasPurpose() || src.hasDataPeriod() || src.hasData() || src.hasExcept()) {
|
||||
org.hl7.fhir.r4.model.Consent.provisionComponent pc = new org.hl7.fhir.r4.model.Consent.provisionComponent();
|
||||
org.hl7.fhir.r4.model.Consent.ProvisionComponent pc = new org.hl7.fhir.r4.model.Consent.ProvisionComponent();
|
||||
if (src.hasPeriod())
|
||||
pc.setPeriod(Period30_40.convertPeriod(src.getPeriod()));
|
||||
for (org.hl7.fhir.dstu3.model.Consent.ConsentActorComponent t : src.getActor())
|
||||
|
@ -104,7 +104,7 @@ public class Consent30_40 {
|
|||
}
|
||||
}
|
||||
if (src.hasProvision()) {
|
||||
org.hl7.fhir.r4.model.Consent.provisionComponent p = src.getProvision();
|
||||
org.hl7.fhir.r4.model.Consent.ProvisionComponent p = src.getProvision();
|
||||
if (p.hasPeriod())
|
||||
tgt.setPeriod(Period30_40.convertPeriod(p.getPeriod()));
|
||||
for (org.hl7.fhir.r4.model.Consent.provisionActorComponent t : p.getActor())
|
||||
|
@ -117,7 +117,7 @@ public class Consent30_40 {
|
|||
tgt.setDataPeriod(Period30_40.convertPeriod(p.getDataPeriod()));
|
||||
for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : p.getData())
|
||||
tgt.addData(convertConsentDataComponent(t));
|
||||
for (org.hl7.fhir.r4.model.Consent.provisionComponent t : p.getProvision())
|
||||
for (org.hl7.fhir.r4.model.Consent.ProvisionComponent t : p.getProvision())
|
||||
tgt.addExcept(convertExceptComponent(t));
|
||||
}
|
||||
return tgt;
|
||||
|
@ -369,7 +369,7 @@ public class Consent30_40 {
|
|||
return tgt;
|
||||
}
|
||||
|
||||
static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException {
|
||||
static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.ProvisionComponent src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.dstu3.model.Consent.ExceptComponent tgt = new org.hl7.fhir.dstu3.model.Consent.ExceptComponent();
|
||||
|
@ -393,10 +393,10 @@ public class Consent30_40 {
|
|||
return tgt;
|
||||
}
|
||||
|
||||
static public org.hl7.fhir.r4.model.Consent.provisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException {
|
||||
static public org.hl7.fhir.r4.model.Consent.ProvisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent();
|
||||
org.hl7.fhir.r4.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r4.model.Consent.ProvisionComponent();
|
||||
ConversionContext30_40.INSTANCE.getVersionConvertor_30_40().copyBackboneElement(src,tgt);
|
||||
if (src.hasType())
|
||||
tgt.setTypeElement(convertConsentExceptType(src.getTypeElement()));
|
||||
|
|
|
@ -25,8 +25,10 @@ import org.hl7.fhir.r4.model.StringType;
|
|||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
|
||||
import org.hl7.fhir.r5.model.UsageContext;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
||||
public class ElementDefinition40_50 {
|
||||
|
||||
public static org.hl7.fhir.r5.model.ElementDefinition convertElementDefinition(org.hl7.fhir.r4.model.ElementDefinition src) throws FHIRException {
|
||||
if (src == null) return null;
|
||||
org.hl7.fhir.r5.model.ElementDefinition tgt = new org.hl7.fhir.r5.model.ElementDefinition();
|
||||
|
@ -616,7 +618,7 @@ public class ElementDefinition40_50 {
|
|||
if (src == null) return null;
|
||||
org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent tgt = new org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent();
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt,
|
||||
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional");
|
||||
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional", ToolingExtensions.EXT_BINDING_ADDITIONAL);
|
||||
if (src.hasStrength()) tgt.setStrengthElement(Enumerations40_50.convertBindingStrength(src.getStrengthElement()));
|
||||
if (src.hasDescription()) tgt.setDescriptionElement(String40_50.convertStringToMarkdown(src.getDescriptionElement()));
|
||||
if (src.hasValueSet()) tgt.setValueSetElement(Canonical40_50.convertCanonical(src.getValueSetElement()));
|
||||
|
@ -624,6 +626,9 @@ public class ElementDefinition40_50 {
|
|||
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional")) {
|
||||
tgt.addAdditional(convertAdditional(ext));
|
||||
}
|
||||
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl(ToolingExtensions.EXT_BINDING_ADDITIONAL)) {
|
||||
tgt.addAdditional(convertAdditional(ext));
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
|
@ -652,12 +657,12 @@ public class ElementDefinition40_50 {
|
|||
return tgt;
|
||||
}
|
||||
|
||||
private static Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
|
||||
private static org.hl7.fhir.r4.model.Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
|
||||
if (src == null) return null;
|
||||
Extension tgt = new Extension();
|
||||
org.hl7.fhir.r4.model.Extension tgt = new Extension(ToolingExtensions.EXT_BINDING_ADDITIONAL);
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt);
|
||||
if (src.hasPurpose()) {
|
||||
tgt.addExtension(new Extension("purpose", new CodeType(src.getPurposeElement().primitiveValue())));
|
||||
tgt.addExtension(new Extension("purpose", new org.hl7.fhir.r4.model.CodeType(src.getPurposeElement().primitiveValue())));
|
||||
}
|
||||
if (src.hasValueSet()) {
|
||||
tgt.addExtension(new Extension("valueSet", Canonical40_50.convertCanonical(src.getValueSetElement())));
|
||||
|
|
|
@ -220,7 +220,7 @@ public class Consent40_50 {
|
|||
return tgt;
|
||||
}
|
||||
|
||||
public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException {
|
||||
public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.ProvisionComponent src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r5.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r5.model.Consent.ProvisionComponent();
|
||||
|
@ -242,15 +242,15 @@ public class Consent40_50 {
|
|||
tgt.setDataPeriod(Period40_50.convertPeriod(src.getDataPeriod()));
|
||||
for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : src.getData())
|
||||
tgt.addData(convertprovisionDataComponent(t));
|
||||
for (org.hl7.fhir.r4.model.Consent.provisionComponent t : src.getProvision())
|
||||
for (org.hl7.fhir.r4.model.Consent.ProvisionComponent t : src.getProvision())
|
||||
tgt.addProvision(convertprovisionComponent(t));
|
||||
return tgt;
|
||||
}
|
||||
|
||||
public static org.hl7.fhir.r4.model.Consent.provisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException {
|
||||
public static org.hl7.fhir.r4.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException {
|
||||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent();
|
||||
org.hl7.fhir.r4.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r4.model.Consent.ProvisionComponent();
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt);
|
||||
// if (src.hasType())
|
||||
// tgt.setTypeElement(convertConsentProvisionType(src.getTypeElement()));
|
||||
|
|
|
@ -230,12 +230,6 @@ public class Enumerations40_50 {
|
|||
case _4_3_0:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._4_3_0);
|
||||
break;
|
||||
case _4_3_0_CIBUILD:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._4_3_0CIBUILD);
|
||||
break;
|
||||
case _4_3_0_SNAPSHOT1:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._4_3_0SNAPSHOT1);
|
||||
break;
|
||||
case _5_0_0:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._5_0_0);
|
||||
break;
|
||||
|
@ -254,6 +248,15 @@ public class Enumerations40_50 {
|
|||
case _5_0_0DRAFTFINAL:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._5_0_0DRAFTFINAL);
|
||||
break;
|
||||
case _6_0_0:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._6_0_0);
|
||||
break;
|
||||
case _6_0_0_BALLOT1:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._6_0_0_BALLOT1);
|
||||
break;
|
||||
case _6_0_0_BALLOT2:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion._6_0_0_BALLOT2);
|
||||
break;
|
||||
default:
|
||||
tgt.setValue(org.hl7.fhir.r5.model.Enumerations.FHIRVersion.NULL);
|
||||
break;
|
||||
|
@ -342,12 +345,6 @@ public class Enumerations40_50 {
|
|||
case _4_3_0:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._4_3_0);
|
||||
break;
|
||||
case _4_3_0CIBUILD:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._4_3_0_CIBUILD);
|
||||
break;
|
||||
case _4_3_0SNAPSHOT1:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._4_3_0_SNAPSHOT1);
|
||||
break;
|
||||
case _5_0_0:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._5_0_0);
|
||||
break;
|
||||
|
@ -366,6 +363,15 @@ public class Enumerations40_50 {
|
|||
case _5_0_0DRAFTFINAL:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._5_0_0DRAFTFINAL);
|
||||
break;
|
||||
case _6_0_0:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._6_0_0);
|
||||
break;
|
||||
case _6_0_0_BALLOT1:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._6_0_0_BALLOT1);
|
||||
break;
|
||||
case _6_0_0_BALLOT2:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion._6_0_0_BALLOT2);
|
||||
break;
|
||||
|
||||
default:
|
||||
tgt.setValue(org.hl7.fhir.r4.model.Enumerations.FHIRVersion.NULL);
|
||||
|
|
|
@ -33,9 +33,11 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
|||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersionEnumFactory;
|
||||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
@ -237,7 +239,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(VersionConvertorFactory_10_30.convertResource(res)));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_10_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_10_50.convertResource(res));
|
||||
|
@ -251,7 +253,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res));
|
||||
|
@ -265,7 +267,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res));
|
||||
|
@ -279,7 +281,21 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res, new BaseAdvisor_30_40(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
}
|
||||
} else if (VersionUtilities.isR4BVer(currentVersion)) {
|
||||
org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(cnt);
|
||||
convertResourceR4B(res);
|
||||
if (VersionUtilities.isR2Ver(version)) {
|
||||
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res, new PR2Handler()));
|
||||
} else if (VersionUtilities.isR2BVer(version)) {
|
||||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res, new BaseAdvisor_30_40(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
|
@ -293,7 +309,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res, new BaseAdvisor_30_50(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(res);
|
||||
|
@ -311,6 +327,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu2.model.ImplementationGuide ig = (org.hl7.fhir.dstu2.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu2.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu2.model.StructureDefinition sd = (org.hl7.fhir.dstu2.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR2B(org.hl7.fhir.dstu2016may.model.Resource res) {
|
||||
|
@ -318,6 +338,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu2016may.model.ImplementationGuide ig = (org.hl7.fhir.dstu2016may.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu2016may.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu2016may.model.StructureDefinition sd = (org.hl7.fhir.dstu2016may.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR3(org.hl7.fhir.dstu3.model.Resource res) {
|
||||
|
@ -325,6 +349,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu3.model.ImplementationGuide ig = (org.hl7.fhir.dstu3.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu3.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu3.model.StructureDefinition sd = (org.hl7.fhir.dstu3.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR4(org.hl7.fhir.r4.model.Resource res) {
|
||||
|
@ -334,6 +362,23 @@ public class NpmPackageVersionConverter {
|
|||
ig.getFhirVersion().add(new org.hl7.fhir.r4.model.Enumeration<>(new org.hl7.fhir.r4.model.Enumerations.FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.r4.model.StructureDefinition) {
|
||||
org.hl7.fhir.r4.model.StructureDefinition sd = (org.hl7.fhir.r4.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(org.hl7.fhir.r4.model.Enumerations.FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR4B(org.hl7.fhir.r4.model.Resource res) {
|
||||
if (res instanceof org.hl7.fhir.r4.model.ImplementationGuide) {
|
||||
org.hl7.fhir.r4.model.ImplementationGuide ig = (org.hl7.fhir.r4.model.ImplementationGuide) res;
|
||||
ig.getFhirVersion().clear();
|
||||
ig.getFhirVersion().add(new org.hl7.fhir.r4.model.Enumeration<>(new org.hl7.fhir.r4.model.Enumerations.FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.r4.model.StructureDefinition) {
|
||||
org.hl7.fhir.r4.model.StructureDefinition sd = (org.hl7.fhir.r4.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(org.hl7.fhir.r4.model.Enumerations.FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,6 +389,10 @@ public class NpmPackageVersionConverter {
|
|||
ig.getFhirVersion().add(new Enumeration<>(new FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof StructureDefinition) {
|
||||
StructureDefinition sd = (StructureDefinition) res;
|
||||
sd.setFhirVersion(FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -45,10 +45,10 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
public static void main(String[] args) throws FHIRException, IOException, ParseException, URISyntaxException {
|
||||
VSACImporter self = new VSACImporter();
|
||||
self.process(args[0], args[1], args[2], "true".equals(args[3]));
|
||||
self.process(args[0], args[1], args[2], "true".equals(args[3]), "true".equals(args[4]));
|
||||
}
|
||||
|
||||
private void process(String source, String dest, String apiKey, boolean onlyNew) throws FHIRException, IOException, URISyntaxException {
|
||||
private void process(String source, String dest, String apiKey, boolean onlyNew, boolean onlyActive) throws FHIRException, IOException, URISyntaxException {
|
||||
CSVReader csv = new CSVReader(ManagedFileAccess.inStream(source));
|
||||
csv.readHeaders();
|
||||
Map<String, String> errs = new HashMap<>();
|
||||
|
@ -75,13 +75,20 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
System.out.println("Loading");
|
||||
List<String> oids = new ArrayList<>();
|
||||
List<String> allOids = new ArrayList<>();
|
||||
while (csv.line()) {
|
||||
String oid = csv.cell("OID");
|
||||
if (!onlyNew || !(ManagedFileAccess.file(Utilities.path(dest, "ValueSet-" + oid + ".json")).exists())) {
|
||||
oids.add(oid);
|
||||
String status = csv.cell("Expansion Status");
|
||||
if (!onlyActive || "Active".equals(status)) {
|
||||
String oid = csv.cell("OID");
|
||||
allOids.add(oid);
|
||||
if (!onlyNew || !(ManagedFileAccess.file(Utilities.path(dest, "ValueSet-" + oid + ".json")).exists())) {
|
||||
oids.add(oid);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(oids);
|
||||
System.out.println("Cleaning");
|
||||
cleanValueSets(allOids, dest);
|
||||
System.out.println("Go: "+oids.size()+" oids");
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
@ -108,6 +115,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
errs.put(oid, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
for (String oid : errs.keySet()) {
|
||||
oo.addIssue().setSeverity(IssueSeverity.ERROR).setCode(IssueType.EXCEPTION).setDiagnostics(errs.get(oid)).addLocation(oid);
|
||||
|
@ -116,6 +124,22 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
System.out.println("Done. " + i + " ValueSets in "+Utilities.describeDuration(System.currentTimeMillis() - tt));
|
||||
}
|
||||
|
||||
private void cleanValueSets(List<String> allOids, String dest) throws IOException {
|
||||
cleanValueSets(allOids, new File(Utilities.path(dest)));
|
||||
}
|
||||
|
||||
private void cleanValueSets(List<String> allOids, File file) {
|
||||
for (File f : file.listFiles()) {
|
||||
if (f.getName().startsWith("ValueSet-")) {
|
||||
String oid = f.getName().substring(9).replace(".json", "");
|
||||
if (!allOids.contains(oid)) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long estimate(int i, int size, long tt) {
|
||||
long elapsed = System.currentTimeMillis() - tt;
|
||||
long average = elapsed / i;
|
||||
|
@ -201,7 +225,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
}
|
||||
vs.setName(makeValidName(vs.getName()));
|
||||
JurisdictionUtilities.setJurisdictionCountry(vs.getJurisdiction(), "US");
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
new JsonParser().setOutputStyle(OutputStyle.NORMAL).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -683,7 +683,7 @@ public class ClientUtils {
|
|||
for (Header h : response.getAllHeaders()) {
|
||||
headers.add(h.toString());
|
||||
}
|
||||
logger.logResponse(response.getStatusLine().toString(), headers, cnt);
|
||||
logger.logResponse(response.getStatusLine().toString(), headers, cnt, 0);
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -625,7 +625,7 @@ public class ClientUtils {
|
|||
for (Header h : response.getAllHeaders()) {
|
||||
headers.add(h.toString());
|
||||
}
|
||||
logger.logResponse(response.getStatusLine().toString(), headers, cnt);
|
||||
logger.logResponse(response.getStatusLine().toString(), headers, cnt, 0);
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.hl7.fhir.dstu3.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -668,12 +669,16 @@ public class Quantity extends Type implements ICompositeType {
|
|||
public Quantity copy() {
|
||||
Quantity dst = new Quantity();
|
||||
copyValues(dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public void copyValues(Quantity dst) {
|
||||
super.copyValues(dst);
|
||||
dst.value = value == null ? null : value.copy();
|
||||
dst.comparator = comparator == null ? null : comparator.copy();
|
||||
dst.unit = unit == null ? null : unit.copy();
|
||||
dst.system = system == null ? null : system.copy();
|
||||
dst.code = code == null ? null : code.copy();
|
||||
return dst;
|
||||
}
|
||||
|
||||
protected Quantity typedCopy() {
|
||||
|
|
|
@ -371,7 +371,7 @@ public class FhirRequestBuilder {
|
|||
|
||||
try {
|
||||
if (logger != null) {
|
||||
logger.logResponse(Integer.toString(responseCode), headerList, responseBody);
|
||||
logger.logResponse(Integer.toString(responseCode), headerList, responseBody, 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error parsing response body passed in to logger ->\n" + e.getLocalizedMessage());
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package org.hl7.fhir.dstu3.model;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hl7.fhir.dstu3.formats.JsonParser;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class MedicationAdministrationCopyTest {
|
||||
|
||||
@DisplayName("Test MedicationAdministration copy")
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
MedicationAdministration beforeCopy = createMedAdminWithDosageDurationExtension();
|
||||
MedicationAdministration afterCopy = beforeCopy.copy();
|
||||
|
||||
System.out.println("---- BEFORE COPY (BEGIN)");
|
||||
System.out.println(new JsonParser().composeString(beforeCopy));
|
||||
System.out.println("---- BEFORE COPY (END)");
|
||||
System.out.println();
|
||||
System.out.println("---- AFTER COPY (BEGIN)");
|
||||
System.out.println(new JsonParser().composeString(afterCopy));
|
||||
System.out.println("---- AFTER COPY (END)");
|
||||
assertTrue(beforeCopy.equalsDeep(afterCopy));
|
||||
}
|
||||
|
||||
private static MedicationAdministration createMedAdminWithDosageDurationExtension() {
|
||||
MedicationAdministration resource = new MedicationAdministration();
|
||||
resource.setId("12345");
|
||||
var dosage = new MedicationAdministration.MedicationAdministrationDosageComponent();
|
||||
dosage.setDose((SimpleQuantity) new SimpleQuantity().setValue(40))
|
||||
.addExtension(new Extension()
|
||||
.setUrl("http://duration")
|
||||
.setValue(new Duration().setValue(5340000)));
|
||||
resource.setDosage(dosage);
|
||||
return resource;
|
||||
}
|
||||
}
|
|
@ -95,13 +95,13 @@ public class FhirRequestBuilderTests {
|
|||
Mockito.doReturn(parser).when(fhirRequestBuilder).getParser(ArgumentMatchers.eq("json"));
|
||||
|
||||
fhirRequestBuilder.unmarshalReference(response, "json");
|
||||
Mockito.verify(logger).logResponse(ArgumentMatchers.eq("200"), ArgumentMatchers.anyList(), AdditionalMatchers.aryEq(RESPONSE_BODY_STRING.getBytes()));
|
||||
Mockito.verify(logger).logResponse(ArgumentMatchers.eq("200"), ArgumentMatchers.anyList(), AdditionalMatchers.aryEq(RESPONSE_BODY_STRING.getBytes()), ArgumentMatchers.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnmarshallFeedLogging() {
|
||||
fhirRequestBuilder.unmarshalFeed(response, "application/json");
|
||||
Mockito.verify(logger).logResponse(ArgumentMatchers.eq("200"), ArgumentMatchers.anyList(), AdditionalMatchers.aryEq(RESPONSE_BODY_STRING.getBytes()));
|
||||
Mockito.verify(logger).logResponse(ArgumentMatchers.eq("200"), ArgumentMatchers.anyList(), AdditionalMatchers.aryEq(RESPONSE_BODY_STRING.getBytes()), ArgumentMatchers.anyLong());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ public class HTMLClientLogger implements ToolingClientLogger {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long start) {
|
||||
if (file == null)
|
||||
return;
|
||||
file.println("<pre>");
|
||||
|
|
|
@ -8400,15 +8400,15 @@ public class JsonParser extends JsonParserBase {
|
|||
parseElementProperties(getJObject(json, "_verificationDate"), res.getVerificationDateElement());
|
||||
}
|
||||
|
||||
protected Consent.provisionComponent parseConsentprovisionComponent(JsonObject json, Consent owner)
|
||||
protected Consent.ProvisionComponent parseConsentprovisionComponent(JsonObject json, Consent owner)
|
||||
throws IOException, FHIRFormatError {
|
||||
Consent.provisionComponent res = new Consent.provisionComponent();
|
||||
Consent.ProvisionComponent res = new Consent.ProvisionComponent();
|
||||
parseConsentprovisionComponentProperties(json, owner, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected void parseConsentprovisionComponentProperties(JsonObject json, Consent owner,
|
||||
Consent.provisionComponent res) throws IOException, FHIRFormatError {
|
||||
Consent.ProvisionComponent res) throws IOException, FHIRFormatError {
|
||||
parseBackboneElementProperties(json, res);
|
||||
if (json.has("type"))
|
||||
res.setTypeElement(parseEnumeration(json.get("type").getAsString(), Consent.ConsentProvisionType.NULL,
|
||||
|
@ -41383,7 +41383,7 @@ public class JsonParser extends JsonParserBase {
|
|||
}
|
||||
}
|
||||
|
||||
protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException {
|
||||
protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException {
|
||||
if (element != null) {
|
||||
open(name);
|
||||
composeConsentprovisionComponentInner(element);
|
||||
|
@ -41391,7 +41391,7 @@ public class JsonParser extends JsonParserBase {
|
|||
}
|
||||
}
|
||||
|
||||
protected void composeConsentprovisionComponentInner(Consent.provisionComponent element) throws IOException {
|
||||
protected void composeConsentprovisionComponentInner(Consent.ProvisionComponent element) throws IOException {
|
||||
composeBackbone(element);
|
||||
if (element.hasTypeElement()) {
|
||||
composeEnumerationCore("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory(), false);
|
||||
|
@ -41454,7 +41454,7 @@ public class JsonParser extends JsonParserBase {
|
|||
;
|
||||
if (element.hasProvision()) {
|
||||
openArray("provision");
|
||||
for (Consent.provisionComponent e : element.getProvision())
|
||||
for (Consent.ProvisionComponent e : element.getProvision())
|
||||
composeConsentprovisionComponent(null, e);
|
||||
closeArray();
|
||||
}
|
||||
|
|
|
@ -4917,7 +4917,7 @@ public class RdfParser extends RdfParserBase {
|
|||
}
|
||||
|
||||
protected void composeConsentprovisionComponent(Complex parent, String parentType, String name,
|
||||
Consent.provisionComponent element, int index) {
|
||||
Consent.ProvisionComponent element, int index) {
|
||||
if (element == null)
|
||||
return;
|
||||
Complex t;
|
||||
|
|
|
@ -6924,9 +6924,9 @@ public class XmlParser extends XmlParserBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected Consent.provisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner)
|
||||
protected Consent.ProvisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner)
|
||||
throws XmlPullParserException, IOException, FHIRFormatError {
|
||||
Consent.provisionComponent res = new Consent.provisionComponent();
|
||||
Consent.ProvisionComponent res = new Consent.ProvisionComponent();
|
||||
parseBackboneAttributes(xpp, res);
|
||||
next(xpp);
|
||||
int eventType = nextNoWhitespace(xpp);
|
||||
|
@ -6941,7 +6941,7 @@ public class XmlParser extends XmlParserBase {
|
|||
}
|
||||
|
||||
protected boolean parseConsentprovisionComponentContent(int eventType, XmlPullParser xpp, Consent owner,
|
||||
Consent.provisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError {
|
||||
Consent.ProvisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError {
|
||||
if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("type")) {
|
||||
res.setTypeElement(
|
||||
parseEnumeration(xpp, Consent.ConsentProvisionType.NULL, new Consent.ConsentProvisionTypeEnumFactory()));
|
||||
|
@ -34008,7 +34008,7 @@ public class XmlParser extends XmlParserBase {
|
|||
}
|
||||
}
|
||||
|
||||
protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException {
|
||||
protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException {
|
||||
if (element != null) {
|
||||
composeElementAttributes(element);
|
||||
xml.enter(FHIR_NS, name);
|
||||
|
@ -34018,7 +34018,7 @@ public class XmlParser extends XmlParserBase {
|
|||
}
|
||||
}
|
||||
|
||||
protected void composeConsentprovisionComponentElements(Consent.provisionComponent element) throws IOException {
|
||||
protected void composeConsentprovisionComponentElements(Consent.ProvisionComponent element) throws IOException {
|
||||
composeBackboneElementElements(element);
|
||||
if (element.hasTypeElement())
|
||||
composeEnumeration("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory());
|
||||
|
@ -34057,7 +34057,7 @@ public class XmlParser extends XmlParserBase {
|
|||
composeConsentprovisionDataComponent("data", e);
|
||||
}
|
||||
if (element.hasProvision()) {
|
||||
for (Consent.provisionComponent e : element.getProvision())
|
||||
for (Consent.ProvisionComponent e : element.getProvision())
|
||||
composeConsentprovisionComponent("provision", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1221,7 +1221,7 @@ public class Consent extends DomainResource {
|
|||
}
|
||||
|
||||
@Block()
|
||||
public static class provisionComponent extends BackboneElement implements IBaseBackboneElement {
|
||||
public static class ProvisionComponent extends BackboneElement implements IBaseBackboneElement {
|
||||
/**
|
||||
* Action to take - permit or deny - when the rule conditions are met. Not
|
||||
* permitted in root rule, required in all nested rules.
|
||||
|
@ -1314,16 +1314,16 @@ public class Consent extends DomainResource {
|
|||
* Rules which provide exceptions to the base rule or subrules.
|
||||
*/
|
||||
@Child(name = "provision", type = {
|
||||
provisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false)
|
||||
ProvisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false)
|
||||
@Description(shortDefinition = "Nested Exception Rules", formalDefinition = "Rules which provide exceptions to the base rule or subrules.")
|
||||
protected List<provisionComponent> provision;
|
||||
protected List<ProvisionComponent> provision;
|
||||
|
||||
private static final long serialVersionUID = -1280172451L;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public provisionComponent() {
|
||||
public ProvisionComponent() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
@ -1357,7 +1357,7 @@ public class Consent extends DomainResource {
|
|||
* extensions. The accessor "getType" gives direct access to the
|
||||
* value
|
||||
*/
|
||||
public provisionComponent setTypeElement(Enumeration<ConsentProvisionType> value) {
|
||||
public ProvisionComponent setTypeElement(Enumeration<ConsentProvisionType> value) {
|
||||
this.type = value;
|
||||
return this;
|
||||
}
|
||||
|
@ -1374,7 +1374,7 @@ public class Consent extends DomainResource {
|
|||
* @param value Action to take - permit or deny - when the rule conditions are
|
||||
* met. Not permitted in root rule, required in all nested rules.
|
||||
*/
|
||||
public provisionComponent setType(ConsentProvisionType value) {
|
||||
public ProvisionComponent setType(ConsentProvisionType value) {
|
||||
if (value == null)
|
||||
this.type = null;
|
||||
else {
|
||||
|
@ -1404,7 +1404,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @param value {@link #period} (The timeframe in this rule is valid.)
|
||||
*/
|
||||
public provisionComponent setPeriod(Period value) {
|
||||
public ProvisionComponent setPeriod(Period value) {
|
||||
this.period = value;
|
||||
return this;
|
||||
}
|
||||
|
@ -1423,7 +1423,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setActor(List<provisionActorComponent> theActor) {
|
||||
public ProvisionComponent setActor(List<provisionActorComponent> theActor) {
|
||||
this.actor = theActor;
|
||||
return this;
|
||||
}
|
||||
|
@ -1445,7 +1445,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addActor(provisionActorComponent t) { // 3
|
||||
public ProvisionComponent addActor(provisionActorComponent t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.actor == null)
|
||||
|
@ -1477,7 +1477,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setAction(List<CodeableConcept> theAction) {
|
||||
public ProvisionComponent setAction(List<CodeableConcept> theAction) {
|
||||
this.action = theAction;
|
||||
return this;
|
||||
}
|
||||
|
@ -1499,7 +1499,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addAction(CodeableConcept t) { // 3
|
||||
public ProvisionComponent addAction(CodeableConcept t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.action == null)
|
||||
|
@ -1533,7 +1533,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setSecurityLabel(List<Coding> theSecurityLabel) {
|
||||
public ProvisionComponent setSecurityLabel(List<Coding> theSecurityLabel) {
|
||||
this.securityLabel = theSecurityLabel;
|
||||
return this;
|
||||
}
|
||||
|
@ -1555,7 +1555,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addSecurityLabel(Coding t) { // 3
|
||||
public ProvisionComponent addSecurityLabel(Coding t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.securityLabel == null)
|
||||
|
@ -1589,7 +1589,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setPurpose(List<Coding> thePurpose) {
|
||||
public ProvisionComponent setPurpose(List<Coding> thePurpose) {
|
||||
this.purpose = thePurpose;
|
||||
return this;
|
||||
}
|
||||
|
@ -1611,7 +1611,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addPurpose(Coding t) { // 3
|
||||
public ProvisionComponent addPurpose(Coding t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.purpose == null)
|
||||
|
@ -1646,7 +1646,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setClass_(List<Coding> theClass_) {
|
||||
public ProvisionComponent setClass_(List<Coding> theClass_) {
|
||||
this.class_ = theClass_;
|
||||
return this;
|
||||
}
|
||||
|
@ -1668,7 +1668,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addClass_(Coding t) { // 3
|
||||
public ProvisionComponent addClass_(Coding t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.class_ == null)
|
||||
|
@ -1701,7 +1701,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setCode(List<CodeableConcept> theCode) {
|
||||
public ProvisionComponent setCode(List<CodeableConcept> theCode) {
|
||||
this.code = theCode;
|
||||
return this;
|
||||
}
|
||||
|
@ -1723,7 +1723,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addCode(CodeableConcept t) { // 3
|
||||
public ProvisionComponent addCode(CodeableConcept t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.code == null)
|
||||
|
@ -1764,7 +1764,7 @@ public class Consent extends DomainResource {
|
|||
* @param value {@link #dataPeriod} (Clinical or Operational Relevant period of
|
||||
* time that bounds the data controlled by this rule.)
|
||||
*/
|
||||
public provisionComponent setDataPeriod(Period value) {
|
||||
public ProvisionComponent setDataPeriod(Period value) {
|
||||
this.dataPeriod = value;
|
||||
return this;
|
||||
}
|
||||
|
@ -1782,7 +1782,7 @@ public class Consent extends DomainResource {
|
|||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setData(List<provisionDataComponent> theData) {
|
||||
public ProvisionComponent setData(List<provisionDataComponent> theData) {
|
||||
this.data = theData;
|
||||
return this;
|
||||
}
|
||||
|
@ -1804,7 +1804,7 @@ public class Consent extends DomainResource {
|
|||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addData(provisionDataComponent t) { // 3
|
||||
public ProvisionComponent addData(provisionDataComponent t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.data == null)
|
||||
|
@ -1828,16 +1828,16 @@ public class Consent extends DomainResource {
|
|||
* @return {@link #provision} (Rules which provide exceptions to the base rule
|
||||
* or subrules.)
|
||||
*/
|
||||
public List<provisionComponent> getProvision() {
|
||||
public List<ProvisionComponent> getProvision() {
|
||||
if (this.provision == null)
|
||||
this.provision = new ArrayList<provisionComponent>();
|
||||
this.provision = new ArrayList<ProvisionComponent>();
|
||||
return this.provision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a reference to <code>this</code> for easy method chaining
|
||||
*/
|
||||
public provisionComponent setProvision(List<provisionComponent> theProvision) {
|
||||
public ProvisionComponent setProvision(List<ProvisionComponent> theProvision) {
|
||||
this.provision = theProvision;
|
||||
return this;
|
||||
}
|
||||
|
@ -1845,25 +1845,25 @@ public class Consent extends DomainResource {
|
|||
public boolean hasProvision() {
|
||||
if (this.provision == null)
|
||||
return false;
|
||||
for (provisionComponent item : this.provision)
|
||||
for (ProvisionComponent item : this.provision)
|
||||
if (!item.isEmpty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public provisionComponent addProvision() { // 3
|
||||
provisionComponent t = new provisionComponent();
|
||||
public ProvisionComponent addProvision() { // 3
|
||||
ProvisionComponent t = new ProvisionComponent();
|
||||
if (this.provision == null)
|
||||
this.provision = new ArrayList<provisionComponent>();
|
||||
this.provision = new ArrayList<ProvisionComponent>();
|
||||
this.provision.add(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
public provisionComponent addProvision(provisionComponent t) { // 3
|
||||
public ProvisionComponent addProvision(ProvisionComponent t) { // 3
|
||||
if (t == null)
|
||||
return this;
|
||||
if (this.provision == null)
|
||||
this.provision = new ArrayList<provisionComponent>();
|
||||
this.provision = new ArrayList<ProvisionComponent>();
|
||||
this.provision.add(t);
|
||||
return this;
|
||||
}
|
||||
|
@ -1872,7 +1872,7 @@ public class Consent extends DomainResource {
|
|||
* @return The first repetition of repeating field {@link #provision}, creating
|
||||
* it if it does not already exist
|
||||
*/
|
||||
public provisionComponent getProvisionFirstRep() {
|
||||
public ProvisionComponent getProvisionFirstRep() {
|
||||
if (getProvision().isEmpty()) {
|
||||
addProvision();
|
||||
}
|
||||
|
@ -2027,7 +2027,7 @@ public class Consent extends DomainResource {
|
|||
this.getData().add((provisionDataComponent) value); // provisionDataComponent
|
||||
return value;
|
||||
case -547120939: // provision
|
||||
this.getProvision().add((provisionComponent) value); // provisionComponent
|
||||
this.getProvision().add((ProvisionComponent) value); // provisionComponent
|
||||
return value;
|
||||
default:
|
||||
return super.setProperty(hash, name, value);
|
||||
|
@ -2059,7 +2059,7 @@ public class Consent extends DomainResource {
|
|||
} else if (name.equals("data")) {
|
||||
this.getData().add((provisionDataComponent) value);
|
||||
} else if (name.equals("provision")) {
|
||||
this.getProvision().add((provisionComponent) value);
|
||||
this.getProvision().add((ProvisionComponent) value);
|
||||
} else
|
||||
return super.setProperty(name, value);
|
||||
return value;
|
||||
|
@ -2088,7 +2088,7 @@ public class Consent extends DomainResource {
|
|||
} else if (name.equals("data")) {
|
||||
this.getData().remove((provisionDataComponent) value);
|
||||
} else if (name.equals("provision")) {
|
||||
this.getProvision().remove((provisionComponent) value);
|
||||
this.getProvision().remove((ProvisionComponent) value);
|
||||
} else
|
||||
super.removeChild(name, value);
|
||||
|
||||
|
@ -2186,13 +2186,13 @@ public class Consent extends DomainResource {
|
|||
return super.addChild(name);
|
||||
}
|
||||
|
||||
public provisionComponent copy() {
|
||||
provisionComponent dst = new provisionComponent();
|
||||
public ProvisionComponent copy() {
|
||||
ProvisionComponent dst = new ProvisionComponent();
|
||||
copyValues(dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public void copyValues(provisionComponent dst) {
|
||||
public void copyValues(ProvisionComponent dst) {
|
||||
super.copyValues(dst);
|
||||
dst.type = type == null ? null : type.copy();
|
||||
dst.period = period == null ? null : period.copy();
|
||||
|
@ -2240,8 +2240,8 @@ public class Consent extends DomainResource {
|
|||
}
|
||||
;
|
||||
if (provision != null) {
|
||||
dst.provision = new ArrayList<provisionComponent>();
|
||||
for (provisionComponent i : provision)
|
||||
dst.provision = new ArrayList<ProvisionComponent>();
|
||||
for (ProvisionComponent i : provision)
|
||||
dst.provision.add(i.copy());
|
||||
}
|
||||
;
|
||||
|
@ -2251,9 +2251,9 @@ public class Consent extends DomainResource {
|
|||
public boolean equalsDeep(Base other_) {
|
||||
if (!super.equalsDeep(other_))
|
||||
return false;
|
||||
if (!(other_ instanceof provisionComponent))
|
||||
if (!(other_ instanceof ProvisionComponent))
|
||||
return false;
|
||||
provisionComponent o = (provisionComponent) other_;
|
||||
ProvisionComponent o = (ProvisionComponent) other_;
|
||||
return compareDeep(type, o.type, true) && compareDeep(period, o.period, true) && compareDeep(actor, o.actor, true)
|
||||
&& compareDeep(action, o.action, true) && compareDeep(securityLabel, o.securityLabel, true)
|
||||
&& compareDeep(purpose, o.purpose, true) && compareDeep(class_, o.class_, true)
|
||||
|
@ -2265,9 +2265,9 @@ public class Consent extends DomainResource {
|
|||
public boolean equalsShallow(Base other_) {
|
||||
if (!super.equalsShallow(other_))
|
||||
return false;
|
||||
if (!(other_ instanceof provisionComponent))
|
||||
if (!(other_ instanceof ProvisionComponent))
|
||||
return false;
|
||||
provisionComponent o = (provisionComponent) other_;
|
||||
ProvisionComponent o = (ProvisionComponent) other_;
|
||||
return compareValues(type, o.type, true);
|
||||
}
|
||||
|
||||
|
@ -3002,7 +3002,7 @@ public class Consent extends DomainResource {
|
|||
*/
|
||||
@Child(name = "provision", type = {}, order = 12, min = 0, max = 1, modifier = false, summary = true)
|
||||
@Description(shortDefinition = "Constraints to the base Consent.policyRule", formalDefinition = "An exception to the base policy of this consent. An exception can be an addition or removal of access permissions.")
|
||||
protected provisionComponent provision;
|
||||
protected ProvisionComponent provision;
|
||||
|
||||
private static final long serialVersionUID = 206528051L;
|
||||
|
||||
|
@ -3669,12 +3669,12 @@ public class Consent extends DomainResource {
|
|||
* @return {@link #provision} (An exception to the base policy of this consent.
|
||||
* An exception can be an addition or removal of access permissions.)
|
||||
*/
|
||||
public provisionComponent getProvision() {
|
||||
public ProvisionComponent getProvision() {
|
||||
if (this.provision == null)
|
||||
if (Configuration.errorOnAutoCreate())
|
||||
throw new Error("Attempt to auto-create Consent.provision");
|
||||
else if (Configuration.doAutoCreate())
|
||||
this.provision = new provisionComponent(); // cc
|
||||
this.provision = new ProvisionComponent(); // cc
|
||||
return this.provision;
|
||||
}
|
||||
|
||||
|
@ -3687,7 +3687,7 @@ public class Consent extends DomainResource {
|
|||
* consent. An exception can be an addition or removal of access
|
||||
* permissions.)
|
||||
*/
|
||||
public Consent setProvision(provisionComponent value) {
|
||||
public Consent setProvision(ProvisionComponent value) {
|
||||
this.provision = value;
|
||||
return this;
|
||||
}
|
||||
|
@ -3883,7 +3883,7 @@ public class Consent extends DomainResource {
|
|||
this.getVerification().add((ConsentVerificationComponent) value); // ConsentVerificationComponent
|
||||
return value;
|
||||
case -547120939: // provision
|
||||
this.provision = (provisionComponent) value; // provisionComponent
|
||||
this.provision = (ProvisionComponent) value; // provisionComponent
|
||||
return value;
|
||||
default:
|
||||
return super.setProperty(hash, name, value);
|
||||
|
@ -3919,7 +3919,7 @@ public class Consent extends DomainResource {
|
|||
} else if (name.equals("verification")) {
|
||||
this.getVerification().add((ConsentVerificationComponent) value);
|
||||
} else if (name.equals("provision")) {
|
||||
this.provision = (provisionComponent) value; // provisionComponent
|
||||
this.provision = (ProvisionComponent) value; // provisionComponent
|
||||
} else
|
||||
return super.setProperty(name, value);
|
||||
return value;
|
||||
|
@ -3952,7 +3952,7 @@ public class Consent extends DomainResource {
|
|||
} else if (name.equals("verification")) {
|
||||
this.getVerification().remove((ConsentVerificationComponent) value);
|
||||
} else if (name.equals("provision")) {
|
||||
this.provision = (provisionComponent) value; // provisionComponent
|
||||
this.provision = (ProvisionComponent) value; // provisionComponent
|
||||
} else
|
||||
super.removeChild(name, value);
|
||||
|
||||
|
@ -4064,7 +4064,7 @@ public class Consent extends DomainResource {
|
|||
} else if (name.equals("verification")) {
|
||||
return addVerification();
|
||||
} else if (name.equals("provision")) {
|
||||
this.provision = new provisionComponent();
|
||||
this.provision = new ProvisionComponent();
|
||||
return this.provision;
|
||||
} else
|
||||
return super.addChild(name);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,7 +64,7 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
if (logger != null) {
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes);
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes, 0);
|
||||
}
|
||||
|
||||
// Reading byte[] clears body. Need to recreate.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long start) {
|
||||
if (DEBUG) {
|
||||
System.out.println(" txlog resp: " + outcome + " " + present(body));
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long start) {
|
||||
if (file == null)
|
||||
return;
|
||||
file.println("\r\n\r\nResponse: \r\n");
|
||||
|
|
|
@ -59,7 +59,7 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
if (logger != null) {
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes);
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes, 0);
|
||||
}
|
||||
|
||||
// Reading byte[] clears body. Need to recreate.
|
||||
|
|
|
@ -134,6 +134,6 @@ class ClientTest {
|
|||
server.takeRequest();
|
||||
Mockito.verify(mockLogger, Mockito.times(1)).logRequest(Mockito.anyString(), Mockito.anyString(), Mockito.anyList(),
|
||||
Mockito.any());
|
||||
Mockito.verify(mockLogger, Mockito.times(1)).logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
Mockito.verify(mockLogger, Mockito.times(1)).logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any(), Mockito.anyLong());
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -413,11 +413,10 @@ public class ProfileUtilities {
|
|||
// note that ProfileUtilities are used re-entrantly internally, so nothing with process state can be here
|
||||
private final IWorkerContext context;
|
||||
private FHIRPathEngine fpe;
|
||||
private List<ValidationMessage> messages;
|
||||
private List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
private List<String> snapshotStack = new ArrayList<String>();
|
||||
private ProfileKnowledgeProvider pkp;
|
||||
// private boolean igmode;
|
||||
private boolean exception;
|
||||
private ValidationOptions terminologyServiceOptions = new ValidationOptions(FhirPublication.R5);
|
||||
private boolean newSlicingProcessing;
|
||||
private String defWebRoot;
|
||||
|
@ -431,11 +430,16 @@ public class ProfileUtilities {
|
|||
private MappingMergeModeOption mappingMergeMode = MappingMergeModeOption.APPEND;
|
||||
private boolean forPublication;
|
||||
private List<StructureDefinition> obligationProfiles = new ArrayList<>();
|
||||
private boolean wantThrowExceptions;
|
||||
|
||||
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.messages = messages;
|
||||
if (messages != null) {
|
||||
this.messages = messages;
|
||||
} else {
|
||||
wantThrowExceptions = true;
|
||||
}
|
||||
this.pkp = pkp;
|
||||
|
||||
this.fpe = fpe;
|
||||
|
@ -447,7 +451,11 @@ public class ProfileUtilities {
|
|||
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.messages = messages;
|
||||
if (messages != null) {
|
||||
this.messages = messages;
|
||||
} else {
|
||||
wantThrowExceptions = true;
|
||||
}
|
||||
this.pkp = pkp;
|
||||
if (context != null) {
|
||||
this.fpe = new FHIRPathEngine(context, this);
|
||||
|
@ -789,7 +797,7 @@ public class ProfileUtilities {
|
|||
ce++;
|
||||
if (e.hasId()) {
|
||||
String msg = "No match found for "+e.getId()+" in the generated snapshot: check that the path and definitions are legal in the differential (including order)";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.differential.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.differential.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
@ -862,19 +870,19 @@ public class ProfileUtilities {
|
|||
slice.getFocus().setMin(count);
|
||||
} else {
|
||||
String msg = "The slice definition for "+slice.getFocus().getId()+" has a minimum of "+slice.getFocus().getMin()+" but the slices add up to a minimum of "+count;
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, forPublication ? ValidationMessage.IssueSeverity.ERROR : ValidationMessage.IssueSeverity.INFORMATION).setIgnorableError(true));
|
||||
}
|
||||
}
|
||||
count = slice.checkMax();
|
||||
if (count > -1 && repeats) {
|
||||
String msg = "The slice definition for "+slice.getFocus().getId()+" has a maximum of "+slice.getFocus().getMax()+" but the slices add up to a maximum of "+count+". Check that this is what is intended";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, ValidationMessage.IssueSeverity.INFORMATION));
|
||||
}
|
||||
if (!slice.checkMinMax()) {
|
||||
String msg = "The slice definition for "+slice.getFocus().getId()+" has a maximum of "+slice.getFocus().getMax()+" which is less than the minimum of "+slice.getFocus().getMin();
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, ValidationMessage.IssueSeverity.WARNING));
|
||||
}
|
||||
slices.remove(s);
|
||||
|
@ -885,13 +893,13 @@ public class ProfileUtilities {
|
|||
}
|
||||
if (ed.hasSliceName() && !slices.containsKey(ed.getPath())) {
|
||||
String msg = "The element "+ed.getId()+" launches straight into slicing without the slicing being set up properly first";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true));
|
||||
}
|
||||
if (ed.hasSliceName() && slices.containsKey(ed.getPath())) {
|
||||
if (!slices.get(ed.getPath()).count(ed, ed.getSliceName())) {
|
||||
String msg = "Duplicate slice name "+ed.getSliceName()+" on "+ed.getId()+" (["+i+"])";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true));
|
||||
}
|
||||
}
|
||||
|
@ -910,10 +918,8 @@ public class ProfileUtilities {
|
|||
}
|
||||
}
|
||||
if (sd == null) {
|
||||
if (messages != null) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE,
|
||||
"StructureDefinition.snapshot.element["+i+"]", "The type of profile "+u.getValue()+" cannot be checked as the profile is not known", IssueSeverity.WARNING));
|
||||
}
|
||||
} else {
|
||||
String wt = t.getWorkingCode();
|
||||
if (ed.getPath().equals("Bundle.entry.response.outcome")) {
|
||||
|
@ -1012,13 +1018,15 @@ public class ProfileUtilities {
|
|||
}
|
||||
|
||||
private void handleError(String url, String msg) {
|
||||
if (exception)
|
||||
throw new DefinitionException(msg);
|
||||
else
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
|
||||
|
||||
private void addMessage(ValidationMessage msg) {
|
||||
messages.add(msg);
|
||||
if (msg.getLevel() == IssueSeverity.ERROR && wantThrowExceptions) {
|
||||
throw new DefinitionException(msg.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void copyInheritedExtensions(StructureDefinition base, StructureDefinition derived, String webUrl) {
|
||||
|
@ -2249,7 +2257,7 @@ public class ProfileUtilities {
|
|||
* Not sure we have enough information here to do the check properly. Might be better done when we're sorting the profile?
|
||||
|
||||
if (i != start && result.isEmpty() && !path.startsWith(context.getElement().get(start).getPath()))
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, IssueType.VALUE, "StructureDefinition.differential.element["+Integer.toString(start)+"]", "Error: unknown element '"+context.getElement().get(start).getPath()+"' (or it is out of order) in profile '"+url+"' (looking for '"+path+"')", IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, IssueType.VALUE, "StructureDefinition.differential.element["+Integer.toString(start)+"]", "Error: unknown element '"+context.getElement().get(start).getPath()+"' (or it is out of order) in profile '"+url+"' (looking for '"+path+"')", IssueSeverity.WARNING));
|
||||
|
||||
*/
|
||||
result.add(context.getElement().get(i));
|
||||
|
@ -2529,7 +2537,7 @@ public class ProfileUtilities {
|
|||
if (derived.hasMinElement()) {
|
||||
if (!Base.compareDeep(derived.getMinElement(), base.getMinElement(), false)) {
|
||||
if (derived.getMin() < base.getMin() && !derived.hasSliceName()) // in a slice, minimum cardinality rules do not apply
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived min ("+Integer.toString(derived.getMin())+") cannot be less than the base min ("+Integer.toString(base.getMin())+") in "+srcSD.getVersionedUrl(), ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived min ("+Integer.toString(derived.getMin())+") cannot be less than the base min ("+Integer.toString(base.getMin())+") in "+srcSD.getVersionedUrl(), ValidationMessage.IssueSeverity.ERROR));
|
||||
base.setMinElement(derived.getMinElement().copy());
|
||||
} else if (trimDifferential)
|
||||
derived.setMinElement(null);
|
||||
|
@ -2540,7 +2548,7 @@ public class ProfileUtilities {
|
|||
if (derived.hasMaxElement()) {
|
||||
if (!Base.compareDeep(derived.getMaxElement(), base.getMaxElement(), false)) {
|
||||
if (isLargerMax(derived.getMax(), base.getMax()))
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived max ("+derived.getMax()+") cannot be greater than the base max ("+base.getMax()+")", ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived max ("+derived.getMax()+") cannot be greater than the base max ("+base.getMax()+")", ValidationMessage.IssueSeverity.ERROR));
|
||||
base.setMaxElement(derived.getMaxElement().copy());
|
||||
} else if (trimDifferential)
|
||||
derived.setMaxElement(null);
|
||||
|
@ -2642,7 +2650,7 @@ public class ProfileUtilities {
|
|||
}
|
||||
if (!(base.hasMustSupportElement() && Base.compareDeep(base.getMustSupportElement(), mse, false))) {
|
||||
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));
|
||||
addMessage(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(mse);
|
||||
} else if (trimDifferential)
|
||||
|
@ -2654,7 +2662,7 @@ public class ProfileUtilities {
|
|||
if (derived.hasMustHaveValueElement()) {
|
||||
if (!(base.hasMustHaveValueElement() && Base.compareDeep(derived.getMustHaveValueElement(), base.getMustHaveValueElement(), false))) {
|
||||
if (base.hasMustHaveValue() && base.getMustHaveValue() && !derived.getMustHaveValue()) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-have-value = false] when [must-have-value = true] in the base profile", ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-have-value = false] when [must-have-value = true] in the base profile", ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
base.setMustHaveValueElement(derived.getMustHaveValueElement().copy());
|
||||
} else if (trimDifferential)
|
||||
|
@ -2721,25 +2729,25 @@ public class ProfileUtilities {
|
|||
|
||||
if (!base.hasBinding() || !Base.compareDeep(derived.getBinding(), base.getBinding(), false)) {
|
||||
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));
|
||||
addMessage(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));
|
||||
// throw new DefinitionException("StructureDefinition "+pn+" at "+derived.getPath()+": illegal attempt to change a binding from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode());
|
||||
else if (base.hasBinding() && derived.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && base.getBinding().hasValueSet() && derived.getBinding().hasValueSet()) {
|
||||
ValueSet baseVs = context.findTxResource(ValueSet.class, base.getBinding().getValueSet(), srcSD);
|
||||
ValueSet contextVs = context.findTxResource(ValueSet.class, derived.getBinding().getValueSet(), derivedSrc);
|
||||
if (baseVs == null) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING));
|
||||
} else if (contextVs == null) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING));
|
||||
} else {
|
||||
ValueSetExpansionOutcome expBase = context.expandVS(baseVs, true, false);
|
||||
ValueSetExpansionOutcome expDerived = context.expandVS(contextVs, true, false);
|
||||
if (expBase.getValueset() == null)
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING));
|
||||
else if (expDerived.getValueset() == null)
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING));
|
||||
else if (ToolingExtensions.hasExtension(expBase.getValueset().getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY)) {
|
||||
if (ToolingExtensions.hasExtension(expDerived.getValueset().getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY) || expDerived.getValueset().getExpansion().getContains().size() > 100) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Unable to check if "+derived.getBinding().getValueSet()+" is a proper subset of " +base.getBinding().getValueSet()+" - base value set is too large to check", ValidationMessage.IssueSeverity.WARNING));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Unable to check if "+derived.getBinding().getValueSet()+" is a proper subset of " +base.getBinding().getValueSet()+" - base value set is too large to check", ValidationMessage.IssueSeverity.WARNING));
|
||||
} else {
|
||||
boolean ok = true;
|
||||
for (ValueSetExpansionContainsComponent cc : expDerived.getValueset().getExpansion().getContains()) {
|
||||
|
@ -2750,11 +2758,11 @@ public class ProfileUtilities {
|
|||
}
|
||||
}
|
||||
if (!ok) {
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
}
|
||||
} else if (!isSubset(expBase.getValueset(), expDerived.getValueset()))
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
}
|
||||
ElementDefinitionBindingComponent d = derived.getBinding();
|
||||
|
@ -2915,7 +2923,7 @@ public class ProfileUtilities {
|
|||
|
||||
private ElementDefinitionBindingAdditionalComponent getMatchingAdditionalBinding(ElementDefinitionBindingComponent nb,ElementDefinitionBindingAdditionalComponent ab) {
|
||||
for (ElementDefinitionBindingAdditionalComponent t : nb.getAdditional()) {
|
||||
if (t.getValueSet() != null && t.getValueSet().equals(ab.getValueSet()) && t.getPurpose() == ab.getPurpose()) {
|
||||
if (t.getValueSet() != null && t.getValueSet().equals(ab.getValueSet()) && t.getPurpose() == ab.getPurpose() && !ab.hasUsage()) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -2965,11 +2973,7 @@ public class ProfileUtilities {
|
|||
if (tgtOk) {
|
||||
ok = true;
|
||||
} else {
|
||||
if (messages == null) {
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_, purl, derived.getPath(), url, td.getTargetProfile()));
|
||||
} else {
|
||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile " + u.getValue() + " is not a valid constraint on the base (" + td.getTargetProfile() + ") at " + derived.getPath(), IssueSeverity.ERROR));
|
||||
}
|
||||
addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), context.formatMessage(I18nConstants.ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_, purl, derived.getPath(), url, td.getTargetProfile()), IssueSeverity.ERROR));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2989,9 +2993,7 @@ public class ProfileUtilities {
|
|||
}
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
||||
if (sd == null) {
|
||||
if (messages != null) {
|
||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+dPath+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
||||
}
|
||||
addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+dPath+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
||||
return true;
|
||||
} else {
|
||||
if (sd.hasBaseDefinition() && sdConformsToTargets(path, dPath, sd.getBaseDefinition(), td)) {
|
||||
|
@ -3022,7 +3024,7 @@ public class ProfileUtilities {
|
|||
|
||||
}
|
||||
if (!ok) {
|
||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.CONFLICT, dest.getId(), "The "+fieldName+" value has type '"+ft+"' which is not valid (valid "+Utilities.pluralize("type", dest.getType().size())+": "+types.toString()+")", IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.CONFLICT, dest.getId(), "The "+fieldName+" value has type '"+ft+"' which is not valid (valid "+Utilities.pluralize("type", dest.getType().size())+": "+types.toString()+")", IssueSeverity.ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3936,10 +3938,7 @@ public class ProfileUtilities {
|
|||
}
|
||||
ed.setId(bs);
|
||||
if (idList.containsKey(bs)) {
|
||||
if (exception || messages == null) {
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.SAME_ID_ON_MULTIPLE_ELEMENTS__IN_, bs, idList.get(bs), ed.getPath(), name));
|
||||
} else
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, "Duplicate Element id "+bs, ValidationMessage.IssueSeverity.ERROR));
|
||||
addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, context.formatMessage(I18nConstants.SAME_ID_ON_MULTIPLE_ELEMENTS__IN_, bs, idList.get(bs), ed.getPath(), name), ValidationMessage.IssueSeverity.ERROR));
|
||||
}
|
||||
idList.put(bs, ed.getPath());
|
||||
if (ed.hasContentReference() && ed.getContentReference().startsWith("#")) {
|
||||
|
@ -4315,12 +4314,12 @@ public class ProfileUtilities {
|
|||
|
||||
|
||||
public boolean isThrowException() {
|
||||
return exception;
|
||||
return wantThrowExceptions;
|
||||
}
|
||||
|
||||
|
||||
public void setThrowException(boolean exception) {
|
||||
this.exception = exception;
|
||||
this.wantThrowExceptions = exception;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4578,7 +4577,10 @@ public class ProfileUtilities {
|
|||
}
|
||||
|
||||
public void setMessages(List<ValidationMessage> messages) {
|
||||
this.messages = messages;
|
||||
if (messages != null) {
|
||||
this.messages = messages;
|
||||
wantThrowExceptions = false;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<Property>> propertyCache = new HashMap<>();
|
||||
|
|
|
@ -1303,6 +1303,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
// ok, first we try to validate locally
|
||||
try {
|
||||
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs, ctxt);
|
||||
if (vsc.getOpContext() != null) {
|
||||
vsc.getOpContext().note("Validate "+code.toString()+" @ "+path+" against "+(vs == null ? "null" : vs.getVersionedUrl()));
|
||||
}
|
||||
vsc.setUnknownSystems(unknownSystems);
|
||||
vsc.setThrowToServer(options.isUseServer() && terminologyClientManager.hasClient());
|
||||
if (!ValueSetUtilities.isServerSide(code.getSystem())) {
|
||||
|
@ -1471,15 +1474,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
protected ValueSetExpander constructValueSetExpanderSimple(ValidationOptions options) {
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options)).setDebug(logger.isDebugLogging());
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options, "expansion")).setDebug(logger.isDebugLogging());
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple(ValidationOptions options, ValueSet vs, ValidationContextCarrier ctxt) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, ctxt, expParameters, terminologyClientManager);
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options, "validation"), options, vs, ctxt, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, terminologyClientManager);
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options, "validation"), options, vs, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected Parameters constructParameters(TerminologyClientContext tcd, ValueSet vs, boolean hierarchical) {
|
||||
|
@ -1643,7 +1646,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
Parameters pIn = constructParameters(options, code);
|
||||
res = validateOnServer(tc, vs, pIn, options);
|
||||
} catch (Exception e) {
|
||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId());
|
||||
issues.clear();
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXCEPTION);
|
||||
iss.getDetails().setText(e.getMessage());
|
||||
issues.add(iss);
|
||||
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), issues).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR);
|
||||
}
|
||||
if (cachingAllowed) {
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.PERMANENT);
|
||||
|
@ -1779,6 +1786,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (options.isDisplayWarningMode()) {
|
||||
pin.addParameter("mode","lenient-display-validation");
|
||||
}
|
||||
pin.addParameter("diagnostics", true);
|
||||
}
|
||||
|
||||
private boolean addDependentResources(TerminologyClientContext tc, Parameters pin, ValueSet vs) {
|
||||
|
|
|
@ -87,7 +87,7 @@ public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long start) {
|
||||
if (DEBUG) {
|
||||
System.out.println(" txlog resp: " +outcome+" "+present(body));
|
||||
}
|
||||
|
|
|
@ -76,10 +76,10 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long length) {
|
||||
if (file == null)
|
||||
return;
|
||||
file.println("\r\n\r\nResponse: \r\n");
|
||||
file.println("\r\n\r\nResponse ("+Utilities.describeDuration(length)+"): \r\n");
|
||||
file.println(outcome);
|
||||
for (String s : headers)
|
||||
file.println(s);
|
||||
|
|
|
@ -162,6 +162,7 @@ public class Element extends Base implements NamedItem {
|
|||
private FhirFormat format;
|
||||
private Object nativeObject;
|
||||
private List<SliceDefinition> sliceDefinitions;
|
||||
private boolean elided;
|
||||
|
||||
public Element(String name) {
|
||||
super();
|
||||
|
@ -1429,6 +1430,8 @@ public class Element extends Base implements NamedItem {
|
|||
public Base copy() {
|
||||
Element element = new Element(this);
|
||||
this.copyValues(element);
|
||||
if (this.isElided())
|
||||
element.setElided(true);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
@ -1638,4 +1641,11 @@ public class Element extends Base implements NamedItem {
|
|||
return FhirPublication.fromCode(property.getStructure().getVersion());
|
||||
}
|
||||
|
||||
public void setElided(boolean elided) {
|
||||
this.elided = elided;
|
||||
}
|
||||
|
||||
public boolean isElided() {
|
||||
return this.elided;
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ import org.hl7.fhir.r5.formats.JsonCreatorDirect;
|
|||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.StringPair;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
|
@ -85,6 +86,8 @@ public class JsonParser extends ParserBase {
|
|||
|
||||
private JsonCreator json;
|
||||
private boolean allowComments;
|
||||
private boolean elideElements;
|
||||
// private boolean suppressResourceType;
|
||||
|
||||
private Element baseElement;
|
||||
private boolean markedXhtml;
|
||||
|
@ -782,7 +785,8 @@ public class JsonParser extends ParserBase {
|
|||
}
|
||||
checkComposeComments(e);
|
||||
json.beginObject();
|
||||
prop("resourceType", e.getType(), null);
|
||||
// if (!isSuppressResourceType())
|
||||
prop("resourceType", e.getType(), null);
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : e.getChildren()) {
|
||||
compose(e.getName(), e, done, child);
|
||||
|
@ -807,7 +811,8 @@ public class JsonParser extends ParserBase {
|
|||
checkComposeComments(e);
|
||||
json.beginObject();
|
||||
|
||||
prop("resourceType", e.getType(), linkResolver == null ? null : linkResolver.resolveProperty(e.getProperty()));
|
||||
// if (!isSuppressResourceType())
|
||||
prop("resourceType", e.getType(), linkResolver == null ? null : linkResolver.resolveProperty(e.getProperty()));
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : e.getChildren()) {
|
||||
compose(e.getName(), e, done, child);
|
||||
|
@ -821,15 +826,50 @@ public class JsonParser extends ParserBase {
|
|||
if (wantCompose(path, child)) {
|
||||
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
|
||||
if (!isList) {// for specials, ignore the cardinality of the stated type
|
||||
compose(path, child);
|
||||
if (child.isElided() && isElideElements() && json.canElide())
|
||||
json.elide();
|
||||
else
|
||||
compose(path, child);
|
||||
} else if (!done.contains(child.getName())) {
|
||||
done.add(child.getName());
|
||||
List<Element> list = e.getChildrenByName(child.getName());
|
||||
composeList(path, list);
|
||||
if (child.getProperty().getDefinition().hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY))
|
||||
composeKeyList(path, list);
|
||||
else
|
||||
composeList(path, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void composeKeyList(String path, List<Element> list) throws IOException {
|
||||
String keyName = list.get(0).getProperty().getDefinition().getExtensionString(ToolingExtensions.EXT_JSON_PROP_KEY);
|
||||
json.name(list.get(0).getName());
|
||||
json.beginObject();
|
||||
for (Element e: list) {
|
||||
Element key = null;
|
||||
Element value = null;
|
||||
for (Element child: e.getChildren()) {
|
||||
if (child.getName().equals(keyName))
|
||||
key = child;
|
||||
else
|
||||
value = child;
|
||||
}
|
||||
if (value.isPrimitive())
|
||||
primitiveValue(key.getValue(), value);
|
||||
else {
|
||||
json.name(key.getValue());
|
||||
checkComposeComments(e);
|
||||
json.beginObject();
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : value.getChildren()) {
|
||||
compose(value.getName(), value, done, child);
|
||||
}
|
||||
json.endObject();
|
||||
compose(path + "." + key.getValue(), value);
|
||||
}
|
||||
}
|
||||
json.endObject();
|
||||
}
|
||||
|
||||
private void composeList(String path, List<Element> list) throws IOException {
|
||||
// there will be at least one element
|
||||
|
@ -847,7 +887,9 @@ public class JsonParser extends ParserBase {
|
|||
if (prim) {
|
||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
for (Element item : list) {
|
||||
if (item.hasValue()) {
|
||||
if (item.isElided() && json.canElide())
|
||||
json.elide();
|
||||
else if (item.hasValue()) {
|
||||
if (linkResolver != null && item.getProperty().isReference()) {
|
||||
String ref = linkResolver.resolveReference(getReferenceForElement(item));
|
||||
if (ref != null) {
|
||||
|
@ -866,7 +908,9 @@ public class JsonParser extends ParserBase {
|
|||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
int i = 0;
|
||||
for (Element item : list) {
|
||||
if (item.hasChildren()) {
|
||||
if (item.isElided() && json.canElide())
|
||||
json.elide();
|
||||
else if (item.hasChildren()) {
|
||||
open(null,null);
|
||||
if (item.getProperty().isResource()) {
|
||||
prop("resourceType", item.getType(), linkResolver == null ? null : linkResolver.resolveType(item.getType()));
|
||||
|
@ -933,9 +977,10 @@ public class JsonParser extends ParserBase {
|
|||
json.externalLink(ref);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : element.getChildren()) {
|
||||
compose(path+"."+element.getName(), element, done, child);
|
||||
compose(path + "." + element.getName(), element, done, child);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
@ -951,5 +996,23 @@ public class JsonParser extends ParserBase {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean isElideElements() {
|
||||
return elideElements;
|
||||
}
|
||||
|
||||
public JsonParser setElideElements(boolean elideElements) {
|
||||
this.elideElements = elideElements;
|
||||
return this;
|
||||
}
|
||||
/*
|
||||
public boolean isSuppressResourceType() {
|
||||
return suppressResourceType;
|
||||
}
|
||||
|
||||
public JsonParser setSuppressResourceType(boolean suppressResourceType) {
|
||||
this.suppressResourceType = suppressResourceType;
|
||||
return this;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
|
@ -94,6 +94,7 @@ import org.xml.sax.XMLReader;
|
|||
public class XmlParser extends ParserBase {
|
||||
private boolean allowXsiLocation;
|
||||
private String version;
|
||||
private boolean elideElements;
|
||||
|
||||
public XmlParser(IWorkerContext context) {
|
||||
super(context);
|
||||
|
@ -805,92 +806,125 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
|
||||
private void composeElement(IXMLWriter xml, Element element, String elementName, boolean root) throws IOException, FHIRException {
|
||||
if (showDecorations) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ElementDecoration> decorations = (List<ElementDecoration>) element.getUserData("fhir.decorations");
|
||||
if (decorations != null)
|
||||
for (ElementDecoration d : decorations)
|
||||
xml.decorate(d);
|
||||
}
|
||||
for (String s : element.getComments()) {
|
||||
xml.comment(s, true);
|
||||
if (!(isElideElements() && element.isElided())) {
|
||||
if (showDecorations) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ElementDecoration> decorations = (List<ElementDecoration>) element.getUserData("fhir.decorations");
|
||||
if (decorations != null)
|
||||
for (ElementDecoration d : decorations)
|
||||
xml.decorate(d);
|
||||
}
|
||||
for (String s : element.getComments()) {
|
||||
xml.comment(s, true);
|
||||
}
|
||||
}
|
||||
if (isText(element.getProperty())) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.enter(element.getProperty().getXmlNamespace(),elementName);
|
||||
if (linkResolver != null && element.getProperty().isReference()) {
|
||||
String ref = linkResolver.resolveReference(getReferenceForElement(element));
|
||||
if (ref != null) {
|
||||
xml.externalLink(ref);
|
||||
if (isElideElements() && element.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.enter(element.getProperty().getXmlNamespace(),elementName);
|
||||
if (linkResolver != null && element.getProperty().isReference()) {
|
||||
String ref = linkResolver.resolveReference(getReferenceForElement(element));
|
||||
if (ref != null) {
|
||||
xml.externalLink(ref);
|
||||
}
|
||||
}
|
||||
xml.text(element.getValue());
|
||||
xml.exit(element.getProperty().getXmlNamespace(),elementName);
|
||||
}
|
||||
xml.text(element.getValue());
|
||||
xml.exit(element.getProperty().getXmlNamespace(),elementName);
|
||||
} else if (!element.hasChildren() && !element.hasValue()) {
|
||||
if (element.getExplicitType() != null)
|
||||
xml.attribute("xsi:type", element.getExplicitType());
|
||||
xml.element(elementName);
|
||||
if (isElideElements() && element.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
if (element.getExplicitType() != null)
|
||||
xml.attribute("xsi:type", element.getExplicitType());
|
||||
xml.element(elementName);
|
||||
}
|
||||
} else if (element.isPrimitive() || (element.hasType() && isPrimitive(element.getType()))) {
|
||||
if (element.getType().equals("xhtml")) {
|
||||
String rawXhtml = element.getValue();
|
||||
if (isCdaText(element.getProperty())) {
|
||||
new CDANarrativeFormat().convert(xml, new XhtmlParser().parseFragment(rawXhtml));
|
||||
} else {
|
||||
xml.escapedText(rawXhtml);
|
||||
if (!markedXhtml) {
|
||||
xml.anchor("end-xhtml");
|
||||
markedXhtml = true;
|
||||
if (isElideElements() && element.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
String rawXhtml = element.getValue();
|
||||
if (isCdaText(element.getProperty())) {
|
||||
new CDANarrativeFormat().convert(xml, new XhtmlParser().parseFragment(rawXhtml));
|
||||
} else {
|
||||
xml.escapedText(rawXhtml);
|
||||
if (!markedXhtml) {
|
||||
xml.anchor("end-xhtml");
|
||||
markedXhtml = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isText(element.getProperty())) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.text(element.getValue());
|
||||
} else {
|
||||
setXsiTypeIfIsTypeAttr(xml, element);
|
||||
if (element.hasValue()) {
|
||||
if (isElideElements() && element.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveType(element.getType()));
|
||||
xml.attribute("value", element.getValue());
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.text(element.getValue());
|
||||
}
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
if (element.hasChildren()) {
|
||||
xml.enter(element.getProperty().getXmlNamespace(), elementName);
|
||||
if (linkResolver != null && element.getProperty().isReference()) {
|
||||
String ref = linkResolver.resolveReference(getReferenceForElement(element));
|
||||
if (ref != null) {
|
||||
xml.externalLink(ref);
|
||||
}
|
||||
} else {
|
||||
if (isElideElements() && element.isElided())
|
||||
xml.attributeElide();
|
||||
else {
|
||||
setXsiTypeIfIsTypeAttr(xml, element);
|
||||
if (element.hasValue()) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveType(element.getType()));
|
||||
xml.attribute("value", element.getValue());
|
||||
}
|
||||
for (Element child : element.getChildren())
|
||||
composeElement(xml, child, child.getName(), false);
|
||||
xml.exit(element.getProperty().getXmlNamespace(),elementName);
|
||||
} else
|
||||
xml.element(elementName);
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
if (element.hasChildren()) {
|
||||
xml.enter(element.getProperty().getXmlNamespace(), elementName);
|
||||
if (linkResolver != null && element.getProperty().isReference()) {
|
||||
String ref = linkResolver.resolveReference(getReferenceForElement(element));
|
||||
if (ref != null) {
|
||||
xml.externalLink(ref);
|
||||
}
|
||||
}
|
||||
for (Element child : element.getChildren())
|
||||
composeElement(xml, child, child.getName(), false);
|
||||
xml.exit(element.getProperty().getXmlNamespace(),elementName);
|
||||
} else
|
||||
xml.element(elementName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setXsiTypeIfIsTypeAttr(xml, element);
|
||||
Set<String> handled = new HashSet<>();
|
||||
if (isElideElements() && element.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
setXsiTypeIfIsTypeAttr(xml, element);
|
||||
Set<String> handled = new HashSet<>();
|
||||
for (Element child : element.getChildren()) {
|
||||
if (!handled.contains(child.getName()) && isAttr(child.getProperty()) && wantCompose(element.getPath(), child)) {
|
||||
handled.add(child.getName());
|
||||
String av = child.getValue();
|
||||
if (child.getProperty().isList()) {
|
||||
for (Element c2 : element.getChildren()) {
|
||||
if (c2 != child && c2.getName().equals(child.getName())) {
|
||||
av = av + " "+c2.getValue();
|
||||
if (isElideElements() && child.isElided())
|
||||
xml.attributeElide();
|
||||
else {
|
||||
String av = child.getValue();
|
||||
if (child.getProperty().isList()) {
|
||||
for (Element c2 : element.getChildren()) {
|
||||
if (c2 != child && c2.getName().equals(child.getName())) {
|
||||
if (c2.isElided())
|
||||
av = av + " ...";
|
||||
else
|
||||
av = av + " " + c2.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveType(child.getType()));
|
||||
if (ToolingExtensions.hasExtension(child.getProperty().getDefinition(), ToolingExtensions.EXT_DATE_FORMAT))
|
||||
av = convertForDateFormatToExternal(ToolingExtensions.readStringExtension(child.getProperty().getDefinition(), ToolingExtensions.EXT_DATE_FORMAT), av);
|
||||
xml.attribute(child.getProperty().getXmlNamespace(), child.getProperty().getXmlName(), av);
|
||||
}
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveType(child.getType()));
|
||||
if (ToolingExtensions.hasExtension(child.getProperty().getDefinition(), ToolingExtensions.EXT_DATE_FORMAT))
|
||||
av = convertForDateFormatToExternal(ToolingExtensions.readStringExtension(child.getProperty().getDefinition(), ToolingExtensions.EXT_DATE_FORMAT), av);
|
||||
xml.attribute(child.getProperty().getXmlNamespace(),child.getProperty().getXmlName(), av);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!element.getProperty().getDefinition().hasExtension(ToolingExtensions.EXT_ID_CHOICE_GROUP)) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
|
@ -914,12 +948,16 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
for (Element child : element.getChildren()) {
|
||||
if (wantCompose(element.getPath(), child)) {
|
||||
if (isText(child.getProperty())) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.text(child.getValue());
|
||||
} else if (!isAttr(child.getProperty())) {
|
||||
composeElement(xml, child, child.getName(), false);
|
||||
if (isElideElements() && child.isElided() && xml.canElide())
|
||||
xml.elide();
|
||||
else {
|
||||
if (isText(child.getProperty())) {
|
||||
if (linkResolver != null)
|
||||
xml.link(linkResolver.resolveProperty(element.getProperty()));
|
||||
xml.text(child.getValue());
|
||||
} else if (!isAttr(child.getProperty())) {
|
||||
composeElement(xml, child, child.getName(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1034,4 +1072,13 @@ public class XmlParser extends ParserBase {
|
|||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isElideElements() {
|
||||
return elideElements;
|
||||
}
|
||||
|
||||
public void setElideElements(boolean elideElements) {
|
||||
this.elideElements = elideElements;
|
||||
}
|
||||
|
||||
}
|
|
@ -71,4 +71,6 @@ public interface JsonCreator {
|
|||
void link(String href);
|
||||
void anchor(String string);
|
||||
void externalLink(String string);
|
||||
void elide();
|
||||
boolean canElide();
|
||||
}
|
|
@ -280,5 +280,12 @@ public class JsonCreatorCanonical implements JsonCreator {
|
|||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canElide() { return false; }
|
||||
|
||||
@Override
|
||||
public void elide() {
|
||||
// not used
|
||||
}
|
||||
|
||||
}
|
|
@ -243,4 +243,12 @@ public class JsonCreatorDirect implements JsonCreator {
|
|||
public void externalLink(String string) {
|
||||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canElide() { return false; }
|
||||
|
||||
@Override
|
||||
public void elide() {
|
||||
// not used
|
||||
}
|
||||
}
|
|
@ -127,4 +127,12 @@ public class JsonCreatorGson implements JsonCreator {
|
|||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elide() {
|
||||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canElide() { return false;}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public class AdditionalBindingsRenderer {
|
|||
private String valueSet;
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private UsageContext usage;
|
||||
private List<UsageContext> usages = new ArrayList<UsageContext>();
|
||||
private boolean any = false;
|
||||
private boolean isUnchanged = false;
|
||||
private boolean matched = false;
|
||||
|
@ -72,7 +72,7 @@ public class AdditionalBindingsRenderer {
|
|||
isUnchanged = isUnchanged && ((valueSet==null && compare.valueSet==null) || valueSet.equals(compare.valueSet));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((usage==null && compare.usage==null) || usage.equals(compare.usage));
|
||||
isUnchanged = isUnchanged && ((usages==null && compare.usages==null) || usages.equals(compare.usages));
|
||||
return isUnchanged;
|
||||
}
|
||||
}
|
||||
|
@ -174,8 +174,12 @@ public class AdditionalBindingsRenderer {
|
|||
abr.purpose = ext.getExtensionString("purpose");
|
||||
abr.valueSet = ext.getExtensionString("valueSet");
|
||||
abr.doco = ext.getExtensionString("documentation");
|
||||
abr.docoShort = ext.getExtensionString("shortDoco");
|
||||
abr.usage = (ext.hasExtension("usage")) && ext.getExtensionByUrl("usage").hasValueUsageContext() ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
||||
abr.docoShort = ext.getExtensionString("shortDoco");
|
||||
for (Extension x : ext.getExtensionsByUrl("usage")) {
|
||||
if (x.hasValueUsageContext()) {
|
||||
abr.usages.add(x.getValueUsageContext());
|
||||
}
|
||||
}
|
||||
abr.any = "any".equals(ext.getExtensionString("scope"));
|
||||
abr.isUnchanged = ext.hasUserData(ProfileUtilities.UD_DERIVATION_EQUALS);
|
||||
return abr;
|
||||
|
@ -187,7 +191,7 @@ public class AdditionalBindingsRenderer {
|
|||
abr.valueSet = ab.getValueSet();
|
||||
abr.doco = ab.getDocumentation();
|
||||
abr.docoShort = ab.getShortDoco();
|
||||
abr.usage = ab.hasUsage() ? ab.getUsageFirstRep() : null;
|
||||
abr.usages.addAll(ab.getUsage());
|
||||
abr.any = ab.getAny();
|
||||
abr.isUnchanged = ab.hasUserData(ProfileUtilities.UD_DERIVATION_EQUALS);
|
||||
return abr;
|
||||
|
@ -220,7 +224,7 @@ public class AdditionalBindingsRenderer {
|
|||
boolean any = false;
|
||||
for (AdditionalBindingDetail binding : bindings) {
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || binding.usage != null || (binding.compare!=null && binding.compare.usage!=null);
|
||||
usage = usage || !binding.usages.isEmpty() || (binding.compare!=null && !binding.compare.usages.isEmpty());
|
||||
any = any || binding.any || (binding.compare!=null && binding.compare.any);
|
||||
}
|
||||
|
||||
|
@ -283,9 +287,12 @@ public class AdditionalBindingsRenderer {
|
|||
renderPurpose(purpose, binding.compare.purpose);
|
||||
}
|
||||
if (usage) {
|
||||
if (binding.usage != null) {
|
||||
// TODO: This isn't rendered at all yet. Ideally, we want it to render with comparison...
|
||||
new DataRenderer(context).renderBase(new RenderingStatus(), tr.td(), binding.usage);
|
||||
if (!binding.usages.isEmpty()) {
|
||||
XhtmlNode td = tr.td();
|
||||
for (UsageContext uc : binding.usages) {
|
||||
td.sep(", ");
|
||||
new DataRenderer(context).renderBase(new RenderingStatus(), td, uc);
|
||||
}
|
||||
} else {
|
||||
tr.td();
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
|||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.SnomedUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
@ -1198,11 +1199,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
|
||||
protected String getLinkForCode(String system, String version, String code) {
|
||||
if ("http://snomed.info/sct".equals(system)) {
|
||||
if (!Utilities.noString(code)) {
|
||||
return "http://snomed.info/id/"+code;
|
||||
} else {
|
||||
return "https://browser.ihtsdotools.org/";
|
||||
}
|
||||
return SnomedUtilities.getSctLink(version, code, context.getContext().getExpansionParameters());
|
||||
} else if ("http://loinc.org".equals(system)) {
|
||||
if (!Utilities.noString(code)) {
|
||||
return "https://loinc.org/"+code;
|
||||
|
@ -1302,6 +1299,10 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
}
|
||||
|
||||
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c) {
|
||||
renderCoding(status, x, c, true);
|
||||
}
|
||||
|
||||
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c, boolean details) {
|
||||
String s = "";
|
||||
if (c.has("display"))
|
||||
s = context.getTranslated(c.child("display"));
|
||||
|
@ -1311,10 +1312,13 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
if (Utilities.noString(s))
|
||||
s = c.primitiveValue("code");
|
||||
|
||||
if (context.isTechnicalMode()) {
|
||||
x.addText(s+" "+context.formatPhrase(RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), " = '", lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")), c.primitiveValue("display"), "')"));
|
||||
} else
|
||||
if (context.isTechnicalMode() && details) {
|
||||
String d = c.primitiveValue("display") == null ? lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")): c.primitiveValue("display");
|
||||
d = context.formatPhrase(d == null || d.equals(c.primitiveValue("code")) ? RenderingContext.DATA_REND_DETAILS_STATED_ND : RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), d);
|
||||
x.addText(s+" "+d);
|
||||
} else {
|
||||
x.span(null, "{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}").addText(s);
|
||||
}
|
||||
}
|
||||
|
||||
public String displayCodeableConcept(ResourceWrapper cc) {
|
||||
|
@ -1860,8 +1864,8 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
}
|
||||
|
||||
public void renderUsageContext(RenderingStatus status, XhtmlNode x, ResourceWrapper u) throws FHIRFormatError, DefinitionException, IOException {
|
||||
renderCoding(status, x, u.child("code"));
|
||||
x.tx(": ");
|
||||
renderCoding(status, x, u.child("code"), false);
|
||||
x.tx(" = ");
|
||||
renderDataType(status, x, u.child("value"));
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
|||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.CodingValidationRequest;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.SnomedUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -750,9 +751,9 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
if (cs == null) {
|
||||
return "?cs-n?";
|
||||
}
|
||||
String ref = (String) cs.getUserData("filename");
|
||||
String ref = cs.getWebPath();
|
||||
if (ref == null) {
|
||||
ref = (String) cs.getWebPath();
|
||||
ref = cs.getUserString("filename");
|
||||
}
|
||||
return ref == null ? null : ref.replace("\\", "/");
|
||||
}
|
||||
|
@ -825,7 +826,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
String s = Utilities.padLeft("", '\u00A0', i*2);
|
||||
td.attribute("style", "white-space:nowrap").addText(s);
|
||||
addCodeToTable(c.getAbstract(), c.getSystem(), c.getCode(), c.getDisplay(), td);
|
||||
addCodeToTable(c.getAbstract(), c.getSystem(), c.getVersion(), c.getCode(), c.getDisplay(), td);
|
||||
td = tr.td();
|
||||
td.addText(c.getSystem());
|
||||
td = tr.td();
|
||||
|
@ -863,7 +864,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
first = false;
|
||||
XhtmlNode span = td.span(null, mapping.comp.getRelationship().toString());
|
||||
span.addText(getCharForRelationship(mapping.comp));
|
||||
addRefToCode(td, mapping.group.getTarget(), m.getLink(), mapping.comp.getCode());
|
||||
addRefToCode(td, mapping.group.getTarget(), null, m.getLink(), mapping.comp.getCode());
|
||||
if (!Utilities.noString(mapping.comp.getComment()))
|
||||
td.i().tx("("+mapping.comp.getComment()+")");
|
||||
}
|
||||
|
@ -900,13 +901,13 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void addCodeToTable(boolean isAbstract, String system, String code, String display, XhtmlNode td) {
|
||||
private void addCodeToTable(boolean isAbstract, String system, String version, String code, String display, XhtmlNode td) {
|
||||
CodeSystem e = getContext().getWorker().fetchCodeSystem(system);
|
||||
if (e == null || (e.getContent() != org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode.COMPLETE && e.getContent() != org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode.FRAGMENT)) {
|
||||
if (isAbstract)
|
||||
td.i().setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).addText(code);
|
||||
else if ("http://snomed.info/sct".equals(system)) {
|
||||
td.ah(context.prefixLocalHref(sctLink(code))).addText(code);
|
||||
td.ah(context.prefixLocalHref(SnomedUtilities.getSctLink(version, code, context.getContext().getExpansionParameters()))).addText(code);
|
||||
} else if ("http://loinc.org".equals(system)) {
|
||||
td.ah(context.prefixLocalHref(LoincLinker.getLinkForCode(code))).addText(code);
|
||||
} else
|
||||
|
@ -928,15 +929,8 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public String sctLink(String code) {
|
||||
// if (snomedEdition != null)
|
||||
// http://browser.ihtsdotools.org/?perspective=full&conceptId1=428041000124106&edition=us-edition&release=v20180301&server=https://prod-browser-exten.ihtsdotools.org/api/snomed&langRefset=900000000000509007
|
||||
return "http://snomed.info/id/"+code;
|
||||
}
|
||||
|
||||
private void addRefToCode(XhtmlNode td, String target, String vslink, String code) {
|
||||
addCodeToTable(false, target, code, null, td);
|
||||
private void addRefToCode(XhtmlNode td, String target, String vslink, String code, String version) {
|
||||
addCodeToTable(false, target, version, code, null, td);
|
||||
// CodeSystem cs = getContext().getWorker().fetchCodeSystem(target);
|
||||
// String cslink = getCsRef(cs);
|
||||
// String link = cslink != null ? cslink+"#"+cs.getId()+"-"+code : vslink+"#"+code;
|
||||
|
@ -1212,10 +1206,10 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
addMapHeaders(addTableHeaderRowStandard(t, false, true, hasDefinition, hasComments, false, false, null, langs, designations, doDesignations), maps);
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, c);
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, c, inc.getVersion());
|
||||
}
|
||||
for (Base b : VersionComparisonAnnotation.getDeleted(inc, "concept" )) {
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, (ConceptReferenceComponent) b);
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, (ConceptReferenceComponent) b, inc.getVersion());
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 0) {
|
||||
|
@ -1312,11 +1306,11 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
|
||||
private void renderConcept(ConceptSetComponent inc, List<String> langs, boolean doDesignations,
|
||||
List<UsedConceptMap> maps, Map<String, String> designations, Map<String, ConceptDefinitionComponent> definitions,
|
||||
XhtmlNode t, boolean hasComments, boolean hasDefinition, ConceptReferenceComponent c) {
|
||||
XhtmlNode t, boolean hasComments, boolean hasDefinition, ConceptReferenceComponent c, String version) {
|
||||
XhtmlNode tr = t.tr();
|
||||
XhtmlNode td = renderStatusRow(c, t, tr);
|
||||
ConceptDefinitionComponent cc = definitions == null ? null : definitions.get(c.getCode());
|
||||
addCodeToTable(false, inc.getSystem(), c.getCode(), c.hasDisplay()? c.getDisplay() : cc != null ? cc.getDisplay() : "", td);
|
||||
addCodeToTable(false, inc.getSystem(), version, c.getCode(), c.hasDisplay()? c.getDisplay() : cc != null ? cc.getDisplay() : "", td);
|
||||
|
||||
td = tr.td();
|
||||
if (!Utilities.noString(c.getDisplay()))
|
||||
|
@ -1355,7 +1349,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
first = false;
|
||||
XhtmlNode span = td.span(null, mapping.comp.getRelationship().toString());
|
||||
span.addText(getCharForRelationship(mapping.comp));
|
||||
addRefToCode(td, mapping.group.getTarget(), m.getLink(), mapping.comp.getCode());
|
||||
addRefToCode(td, mapping.group.getTarget(), m.getLink(), mapping.comp.getCode(), version);
|
||||
if (!Utilities.noString(mapping.comp.getComment()))
|
||||
td.i().tx("("+mapping.comp.getComment()+")");
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ public class TerminologyClientContext {
|
|||
|
||||
}
|
||||
|
||||
private static boolean canUseCacheId;
|
||||
|
||||
private ITerminologyClient client;
|
||||
private boolean initialised = false;
|
||||
private CapabilityStatement capabilitiesStatementQuick;
|
||||
|
@ -180,7 +182,7 @@ public class TerminologyClientContext {
|
|||
txCache.cacheTerminologyCapabilities(getAddress(), txcaps);
|
||||
}
|
||||
}
|
||||
if (txcaps != null) {
|
||||
if (txcaps != null && TerminologyClientContext.canUseCacheId) {
|
||||
for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) {
|
||||
if ("cache-id".equals(t.getName())) {
|
||||
setTxCaching(true);
|
||||
|
@ -207,5 +209,12 @@ public class TerminologyClientContext {
|
|||
return client.getAddress();
|
||||
}
|
||||
|
||||
public static boolean isCanUseCacheId() {
|
||||
return canUseCacheId;
|
||||
}
|
||||
|
||||
public static void setCanUseCacheId(boolean canUseCacheId) {
|
||||
TerminologyClientContext.canUseCacheId = canUseCacheId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
private ValueSetExpansionContainsComponent addCode(WorkingContext wc, String system, String code, String display, String dispLang, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
||||
boolean isAbstract, boolean inactive, List<ValueSet> filters, boolean noInactive, boolean deprecated, List<ValueSetExpansionPropertyComponent> vsProp,
|
||||
List<ConceptPropertyComponent> csProps, CodeSystem cs, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList, ValueSetExpansionComponent exp) throws ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("addCode"+code);
|
||||
|
||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code, exp))
|
||||
return null;
|
||||
|
@ -447,7 +447,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("addCodeAndDescendents");
|
||||
focus.checkNoModifiers("Expansion.contains", "expanding");
|
||||
ValueSetExpansionContainsComponent np = null;
|
||||
for (String code : getCodesForConcept(focus, expParams)) {
|
||||
|
@ -497,7 +497,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private void addCodeAndDescendents(WorkingContext wc, CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, ConceptFilter filterFunc, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, List<WorkingContext> otherFilters, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("addCodeAndDescendents");
|
||||
def.checkNoModifiers("Code in Code System", "expanding");
|
||||
if (exclusion != null) {
|
||||
if (exclusion.getCode().equals(def.getCode()))
|
||||
|
@ -528,7 +528,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private void excludeCodeAndDescendents(WorkingContext wc, CodeSystem cs, String system, ConceptDefinitionComponent def, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, ConceptFilter filterFunc, List<WorkingContext> otherFilters, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("excludeCodeAndDescendents");
|
||||
def.checkNoModifiers("Code in Code System", "expanding");
|
||||
if (exclusion != null) {
|
||||
if (exclusion.getCode().equals(def.getCode()))
|
||||
|
@ -596,7 +596,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void excludeCodes(WorkingContext wc, ConceptSetComponent exc, Parameters expParams, ValueSetExpansionComponent exp, ValueSet vs) throws FHIRException, FileNotFoundException, ETooCostly, IOException {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("excludeCodes");
|
||||
exc.checkNoModifiers("Compose.exclude", "expanding");
|
||||
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
||||
wc.getExcludeSystems().add(exc.getSystem());
|
||||
|
@ -639,7 +639,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void excludeCodes(WorkingContext wc, ValueSetExpansionComponent expand) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("excludeCodes");
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(wc, c.getSystem(), c.getCode());
|
||||
}
|
||||
|
@ -959,7 +959,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
public void copyExpansion(WorkingContext wc,List<ValueSetExpansionContainsComponent> list) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("copyExpansion");
|
||||
for (ValueSetExpansionContainsComponent cc : list) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(cc.getSystem());
|
||||
|
@ -988,7 +988,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
private int copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
|
||||
int count = 0;
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("copyImportContains");
|
||||
for (ValueSetExpansionContainsComponent c : list) {
|
||||
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
|
||||
ValueSetExpansionContainsComponent np = addCode(dwc, c.getSystem(), c.getCode(), c.getDisplay(), vsSrc.getLanguage(), parent, null, expParams, c.getAbstract(), c.getInactive(),
|
||||
|
@ -1002,7 +1002,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void includeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, boolean heirarchical, boolean noInactive, List<Extension> extensions, ValueSet valueSet) throws ETooCostly, FileNotFoundException, IOException, FHIRException, CodeSystemProviderExtension {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("includeCodes");
|
||||
inc.checkNoModifiers("Compose.include", "expanding");
|
||||
List<ValueSet> imports = new ArrayList<ValueSet>();
|
||||
for (CanonicalType imp : inc.getValueSet()) {
|
||||
|
@ -1033,7 +1033,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void doServerIncludeCodes(ConceptSetComponent inc, boolean heirarchical, ValueSetExpansionComponent exp, List<ValueSet> imports, Parameters expParams, List<Extension> extensions, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws FHIRException, CodeSystemProviderExtension, ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("doServerIncludeCodes");
|
||||
CodeSystemProvider csp = CodeSystemProvider.factory(inc.getSystem());
|
||||
if (csp != null) {
|
||||
csp.includeCodes(inc, heirarchical, exp, imports, expParams, extensions, noInactive, vsProps);
|
||||
|
@ -1075,7 +1075,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
|
||||
|
||||
public void doInternalIncludeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, List<ValueSet> imports, CodeSystem cs, boolean noInactive, Resource vsSrc) throws NoTerminologyServiceException, TerminologyServiceException, FHIRException, ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("doInternalIncludeCodes");
|
||||
if (cs == null) {
|
||||
if (context.isNoTerminologyServer())
|
||||
throw failTSE("Unable to find code system " + inc.getSystem().toString());
|
||||
|
@ -1160,7 +1160,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
private void processFilter(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, List<ValueSet> imports, CodeSystem cs, boolean noInactive,
|
||||
ConceptSetFilterComponent fc, WorkingContext wc, List<WorkingContext> filters, boolean exclude)
|
||||
throws ETooCostly {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("processFilter");
|
||||
if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISA) {
|
||||
// special: all codes in the target code system under the value
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
|
@ -1213,7 +1213,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
||||
if (def.getDisplay().contains(fc.getValue()) && passesOtherFilters(filters, cs, def.getCode())) {
|
||||
for (String code : getCodesForConcept(def, expParams)) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("processFilter2");
|
||||
if (exclude) {
|
||||
excludeCode(wc, inc.getSystem(), code);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package org.hl7.fhir.r5.terminologies.utilities;
|
||||
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
|
||||
//URL: http://snomed.info/sct/[module]/version/[e.g. 20150131]'
|
||||
//International: 900000000000207008
|
||||
//US: 731000124108
|
||||
//Australia: 32506021000036107
|
||||
//Belgium: 11000172109
|
||||
//Canada: 20611000087101
|
||||
//Spain: 449081005
|
||||
//Denmark: 554471000005108
|
||||
//Netherlands: 11000146104
|
||||
//Sweden: 45991000052106
|
||||
//Switzerland: 2011000195101
|
||||
//UK: 83821000000107
|
||||
//IPS: 827022005
|
||||
|
||||
public class SnomedUtilities {
|
||||
|
||||
public static String getVersionFromParameters(Parameters p, String version) {
|
||||
for (ParametersParameterComponent pp : p.getParameter()) {
|
||||
switch (pp.getName()) {
|
||||
case "system-version" :
|
||||
if (version == null) {
|
||||
return pp.getValue().primitiveValue();
|
||||
}
|
||||
case "force-system-version":
|
||||
return pp.getValue().primitiveValue();
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
public static String getEditionFromVersion(String version) {
|
||||
if (version == null) {
|
||||
return null;
|
||||
}
|
||||
if (version.startsWith("http://snomed.info/sct/")) {
|
||||
version = version.substring(23);
|
||||
}
|
||||
if (version.contains("/")) {
|
||||
version = version.substring(0, version.indexOf("/"));
|
||||
}
|
||||
if (Utilities.existsInList(version, "900000000000207008", "731000124108", "32506021000036107", "11000172109", "20611000087101",
|
||||
"449081005", "554471000005108", "11000146104", "45991000052106", "2011000195101", "83821000000107", "827022005")) {
|
||||
return version;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSctLink(String version, String code, Parameters p) {
|
||||
if (!Utilities.noString(code)) {
|
||||
version = SnomedUtilities.getVersionFromParameters(p, version);
|
||||
String edId = SnomedUtilities.getEditionFromVersion(version);
|
||||
if (edId != null) {
|
||||
// if there's a version that's an edition, then:
|
||||
// http://snomed.info/sct/11000172109/id//371305003
|
||||
return "http://snomed.info/sct/"+edId+"/id/"+code;
|
||||
} else {
|
||||
// no, version:
|
||||
return "http://snomed.info/id/"+code;
|
||||
}
|
||||
} else {
|
||||
return "https://browser.ihtsdotools.org/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,22 +302,26 @@ public class TerminologyCache {
|
|||
this.lock = lock;
|
||||
if (folder == null) {
|
||||
folder = Utilities.path("[tmp]", "default-tx-cache");
|
||||
} else if ("n/a".equals(folder)) {
|
||||
// this is a weird way to do things but it maintains the legacy interface
|
||||
folder = null;
|
||||
}
|
||||
this.folder = folder;
|
||||
requestCount = 0;
|
||||
hitCount = 0;
|
||||
networkCount = 0;
|
||||
|
||||
|
||||
File f = ManagedFileAccess.file(folder);
|
||||
if (!f.exists()) {
|
||||
Utilities.createDirectory(folder);
|
||||
if (folder != null) {
|
||||
File f = ManagedFileAccess.file(folder);
|
||||
if (!f.exists()) {
|
||||
Utilities.createDirectory(folder);
|
||||
}
|
||||
if (!f.exists()) {
|
||||
throw new IOException("Unable to create terminology cache at "+folder);
|
||||
}
|
||||
checkVersion();
|
||||
load();
|
||||
}
|
||||
if (!f.exists()) {
|
||||
throw new IOException("Unable to create terminology cache at "+folder);
|
||||
}
|
||||
checkVersion();
|
||||
load();
|
||||
}
|
||||
|
||||
private void checkVersion() throws IOException {
|
||||
|
@ -361,7 +365,9 @@ public class TerminologyCache {
|
|||
}
|
||||
|
||||
private void clear() throws IOException {
|
||||
Utilities.clearDirectory(folder);
|
||||
if (folder != null) {
|
||||
Utilities.clearDirectory(folder);
|
||||
}
|
||||
caches.clear();
|
||||
vsCache.clear();
|
||||
csCache.clear();
|
||||
|
@ -1039,7 +1045,7 @@ public class TerminologyCache {
|
|||
|
||||
public SourcedValueSet getValueSet(String canonical) {
|
||||
SourcedValueSetEntry sp = vsCache.get(canonical);
|
||||
if (sp == null) {
|
||||
if (sp == null || folder == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
|
@ -1052,7 +1058,7 @@ public class TerminologyCache {
|
|||
|
||||
public SourcedCodeSystem getCodeSystem(String canonical) {
|
||||
SourcedCodeSystemEntry sp = csCache.get(canonical);
|
||||
if (sp == null) {
|
||||
if (sp == null || folder == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
|
@ -1073,7 +1079,9 @@ public class TerminologyCache {
|
|||
} else {
|
||||
String uuid = Utilities.makeUuidLC();
|
||||
String fn = "vs-"+uuid+".json";
|
||||
new JsonParser().compose(ManagedFileAccess.outStream(Utilities.path(folder, fn)), svs.getVs());
|
||||
if (folder != null) {
|
||||
new JsonParser().compose(ManagedFileAccess.outStream(Utilities.path(folder, fn)), svs.getVs());
|
||||
}
|
||||
vsCache.put(canonical, new SourcedValueSetEntry(svs.getServer(), fn));
|
||||
}
|
||||
org.hl7.fhir.utilities.json.model.JsonObject j = new org.hl7.fhir.utilities.json.model.JsonObject();
|
||||
|
@ -1090,7 +1098,9 @@ public class TerminologyCache {
|
|||
j.add(k, e);
|
||||
}
|
||||
}
|
||||
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, ManagedFileAccess.file(Utilities.path(folder, "vs-externals.json")), true);
|
||||
if (folder != null) {
|
||||
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, ManagedFileAccess.file(Utilities.path(folder, "vs-externals.json")), true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -1106,7 +1116,9 @@ public class TerminologyCache {
|
|||
} else {
|
||||
String uuid = Utilities.makeUuidLC();
|
||||
String fn = "cs-"+uuid+".json";
|
||||
new JsonParser().compose(ManagedFileAccess.outStream(Utilities.path(folder, fn)), scs.getCs());
|
||||
if (folder != null) {
|
||||
new JsonParser().compose(ManagedFileAccess.outStream(Utilities.path(folder, fn)), scs.getCs());
|
||||
}
|
||||
csCache.put(canonical, new SourcedCodeSystemEntry(scs.getServer(), fn));
|
||||
}
|
||||
org.hl7.fhir.utilities.json.model.JsonObject j = new org.hl7.fhir.utilities.json.model.JsonObject();
|
||||
|
@ -1123,7 +1135,9 @@ public class TerminologyCache {
|
|||
j.add(k, e);
|
||||
}
|
||||
}
|
||||
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, ManagedFileAccess.file(Utilities.path(folder, "cs-externals.json")), true);
|
||||
if (folder != null) {
|
||||
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, ManagedFileAccess.file(Utilities.path(folder, "cs-externals.json")), true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.hl7.fhir.exceptions.TerminologyServiceException;
|
|||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.TerminologyServiceProtectionException;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
|
||||
|
@ -38,16 +39,22 @@ public class TerminologyOperationContext {
|
|||
public static boolean debugging = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().toString().indexOf("-agentlib:jdwp") > 0;
|
||||
private static final int EXPANSION_DEAD_TIME_SECS = 60;
|
||||
private long deadTime;
|
||||
private int nestCount = 0;
|
||||
private long startTime;
|
||||
private List<String> contexts = new ArrayList<>();
|
||||
private IWorkerContext worker;
|
||||
private boolean original;
|
||||
private ValidationOptions options;
|
||||
private String name;
|
||||
private List<String> notes = new ArrayList<>();
|
||||
|
||||
public TerminologyOperationContext(IWorkerContext worker, ValidationOptions options) {
|
||||
public TerminologyOperationContext(IWorkerContext worker, ValidationOptions options, String name) {
|
||||
super();
|
||||
this.worker = worker;
|
||||
this.original = true;
|
||||
this.options = options;
|
||||
this.name = name;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
||||
if (EXPANSION_DEAD_TIME_SECS == 0 || debugging) {
|
||||
deadTime = 0;
|
||||
|
@ -56,22 +63,33 @@ public class TerminologyOperationContext {
|
|||
}
|
||||
}
|
||||
|
||||
private TerminologyOperationContext(ValidationOptions options) {
|
||||
private TerminologyOperationContext(ValidationOptions options, String name) {
|
||||
super();
|
||||
this.options = options;
|
||||
this.name = name;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public TerminologyOperationContext copy() {
|
||||
TerminologyOperationContext ret = new TerminologyOperationContext(this.options);
|
||||
TerminologyOperationContext ret = new TerminologyOperationContext(this.options, name);
|
||||
ret.worker = worker;
|
||||
ret.contexts.addAll(contexts);
|
||||
ret.deadTime = deadTime;
|
||||
ret.notes = notes;
|
||||
ret.startTime = startTime;
|
||||
ret.nestCount = nestCount + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void deadCheck() {
|
||||
public void deadCheck(String note) {
|
||||
note(note);
|
||||
if (deadTime != 0 && System.currentTimeMillis() > deadTime) {
|
||||
throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY);
|
||||
System.out.println();
|
||||
System.out.println("Operation took too long - longer than "+(deadTime - startTime)+"ms");
|
||||
for (String s : notes) {
|
||||
System.out.println(s);
|
||||
}
|
||||
throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS, name+" (local)"), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,5 +108,8 @@ public class TerminologyOperationContext {
|
|||
return options;
|
||||
}
|
||||
|
||||
|
||||
public void note(String s) {
|
||||
s = Utilities.padLeft("", ' ', nestCount)+" "+(System.currentTimeMillis() - startTime)+" "+s;
|
||||
notes.add(s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,6 +230,10 @@ public class ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
|
||||
public TerminologyOperationContext getOpContext() {
|
||||
return opContext;
|
||||
}
|
||||
|
||||
|
||||
protected AlternateCodesProcessingRules altCodeParams = new AlternateCodesProcessingRules(false);
|
||||
protected AlternateCodesProcessingRules allAltCodes = new AlternateCodesProcessingRules(true);
|
||||
|
|
|
@ -175,11 +175,15 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private void analyseValueSet() {
|
||||
opContext.note("analyse");
|
||||
if (valueset != null) {
|
||||
opContext.note("vs = "+valueset.getVersionedUrl());
|
||||
opContext.seeContext(valueset.getVersionedUrl());
|
||||
for (Extension s : valueset.getExtensionsByUrl(ExtensionConstants.EXT_VSSUPPLEMENT)) {
|
||||
requiredSupplements.add(s.getValue().primitiveValue());
|
||||
}
|
||||
} else {
|
||||
opContext.note("vs = null");
|
||||
}
|
||||
|
||||
altCodeParams.seeParameters(expansionProfile);
|
||||
|
@ -187,17 +191,18 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
if (localContext != null) {
|
||||
if (valueset != null) {
|
||||
for (ConceptSetComponent i : valueset.getCompose().getInclude()) {
|
||||
analyseComponent(i);
|
||||
analyseComponent(i, "inc"+i);
|
||||
}
|
||||
for (ConceptSetComponent i : valueset.getCompose().getExclude()) {
|
||||
analyseComponent(i);
|
||||
analyseComponent(i, "exc"+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
opContext.note("analysed");
|
||||
}
|
||||
|
||||
private void analyseComponent(ConceptSetComponent i) {
|
||||
opContext.deadCheck();
|
||||
private void analyseComponent(ConceptSetComponent i, String name) {
|
||||
opContext.deadCheck("analyse Component "+name);
|
||||
if (i.getSystemElement().hasExtension(ToolingExtensions.EXT_VALUESET_SYSTEM)) {
|
||||
String ref = i.getSystemElement().getExtensionString(ToolingExtensions.EXT_VALUESET_SYSTEM);
|
||||
if (ref.startsWith("#")) {
|
||||
|
@ -219,12 +224,16 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
public ValidationResult validateCode(String path, CodeableConcept code) throws FHIRException {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("validate "+code.toString());
|
||||
checkValueSetOptions();
|
||||
|
||||
// first, we validate the codings themselves
|
||||
ValidationProcessInfo info = new ValidationProcessInfo();
|
||||
|
||||
if (throwToServer) {
|
||||
checkValueSetLoad(info);
|
||||
}
|
||||
|
||||
CodeableConcept vcc = new CodeableConcept();
|
||||
List<ValidationResult> resList = new ArrayList<>();
|
||||
|
||||
|
@ -395,6 +404,45 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkValueSetLoad(ValidationProcessInfo info) {
|
||||
int serverCount = getServerLoad(info);
|
||||
// There's a trade off here: if we're going to hit the server inside the components, then
|
||||
// the amount of value set collateral we send is limited, but we pay the price of hitting
|
||||
// the server multiple times. If, on the other hand, we give up on that, and hit the server
|
||||
// directly, we have to send value set collateral (though we cache at the higher level)
|
||||
//
|
||||
// the cutoff value is chosen experimentally
|
||||
if (serverCount > 2) {
|
||||
throw new VSCheckerException("This value set is better processed on the server for performance reasons", null, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int getServerLoad(ValidationProcessInfo info) {
|
||||
int serverCount = 0;
|
||||
if (valueset != null) {
|
||||
for (ConceptSetComponent inc : valueset.getCompose().getInclude()) {
|
||||
serverCount = serverCount + checkValueSetLoad(inc, info);
|
||||
}
|
||||
for (ConceptSetComponent inc : valueset.getCompose().getExclude()) {
|
||||
serverCount = serverCount + checkValueSetLoad(inc, info);
|
||||
}
|
||||
}
|
||||
return serverCount;
|
||||
}
|
||||
|
||||
private int checkValueSetLoad(ConceptSetComponent inc, ValidationProcessInfo info) {
|
||||
int serverCount = 0;
|
||||
for (UriType uri : inc.getValueSet()) {
|
||||
ValueSetValidator vsv = getVs(uri.getValue(), info);
|
||||
serverCount += vsv.getServerLoad(info);
|
||||
}
|
||||
CodeSystem cs = resolveCodeSystem(inc.getSystem(), inc.getVersion());
|
||||
if (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT)) {
|
||||
serverCount++;
|
||||
}
|
||||
return serverCount;
|
||||
}
|
||||
|
||||
private boolean checkRequiredSupplements(ValidationProcessInfo info) {
|
||||
if (!requiredSupplements.isEmpty()) {
|
||||
String msg= context.formatMessagePlural(requiredSupplements.size(), I18nConstants.VALUESET_SUPPLEMENT_MISSING, CommaSeparatedStringBuilder.build(requiredSupplements));
|
||||
|
@ -466,7 +514,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
public ValidationResult validateCode(String path, Coding code) throws FHIRException {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("validate "+code.toString());
|
||||
checkValueSetOptions();
|
||||
|
||||
String warningMessage = null;
|
||||
|
@ -798,7 +846,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
|
||||
private ValidationResult findCodeInExpansion(Coding code, List<ValueSetExpansionContainsComponent> contains) {
|
||||
for (ValueSetExpansionContainsComponent containsComponent: contains) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("findCodeInExpansion");
|
||||
if (containsComponent.getSystem().equals(code.getSystem()) && containsComponent.getCode().equals(code.getCode())) {
|
||||
ConceptDefinitionComponent ccd = new ConceptDefinitionComponent();
|
||||
ccd.setCode(containsComponent.getCode());
|
||||
|
@ -825,7 +873,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
|
||||
private boolean checkExpansion(Coding code, List<ValueSetExpansionContainsComponent> contains, VersionInfo vi) {
|
||||
for (ValueSetExpansionContainsComponent containsComponent: contains) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("checkExpansion: "+code.toString());
|
||||
if (containsComponent.hasSystem() && containsComponent.hasCode() && containsComponent.getSystem().equals(code.getSystem()) && containsComponent.getCode().equals(code.getCode())) {
|
||||
vi.setExpansionVersion(containsComponent.getVersion());
|
||||
return true;
|
||||
|
@ -882,7 +930,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
for (ConceptDefinitionDesignationComponent ds : cc.getDesignation()) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("validateCode1 "+ds.toString());
|
||||
if (isOkLanguage(ds.getLanguage())) {
|
||||
b.append("'"+ds.getValue()+"' ("+ds.getLanguage()+")");
|
||||
if (code.getDisplay().equalsIgnoreCase(ds.getValue())) {
|
||||
|
@ -904,7 +952,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
}
|
||||
for (ConceptReferenceDesignationComponent ds : vs.getCc().getDesignation()) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("validateCode2 "+ds.toString());
|
||||
if (isOkLanguage(ds.getLanguage())) {
|
||||
b.append("'"+ds.getValue()+"'");
|
||||
if (code.getDisplay().equalsIgnoreCase(ds.getValue())) {
|
||||
|
@ -1009,7 +1057,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
return null;
|
||||
// if it has an expansion
|
||||
for (ValueSetExpansionContainsComponent exp : valueset.getExpansion().getContains()) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("findValueSetRef "+exp.toString());
|
||||
if (system.equals(exp.getSystem()) && code.equals(exp.getCode())) {
|
||||
ConceptReferenceComponent cc = new ConceptReferenceComponent();
|
||||
cc.setDisplay(exp.getDisplay());
|
||||
|
@ -1048,7 +1096,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private ConceptDefinitionComponent findCodeInConcept(ConceptDefinitionComponent concept, String code, boolean caseSensitive, AlternateCodesProcessingRules altCodeRules) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("findCodeInConcept: "+code.toString()+", "+concept.toString());
|
||||
if (code.equals(concept.getCode())) {
|
||||
return concept;
|
||||
}
|
||||
|
@ -1121,7 +1169,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
|
||||
int i = 0;
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("scanForCodeInValueSet: "+code.toString());
|
||||
if (scanForCodeInValueSetInclude(code, sys, problems, i, vsi)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1241,7 +1289,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
*/
|
||||
private boolean checkSystems(List<ValueSetExpansionContainsComponent> contains, String code, Set<String> systems, List<StringWithCode> problems) {
|
||||
for (ValueSetExpansionContainsComponent c: contains) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("checkSystems "+code.toString());
|
||||
if (c.getCode().equals(code)) {
|
||||
systems.add(c.getSystem());
|
||||
}
|
||||
|
@ -1255,7 +1303,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
if (valueset == null) {
|
||||
return null;
|
||||
}
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("codeInValueSet: "+system+"#"+code);
|
||||
checkCanonical(info.getIssues(), path, valueset, valueset);
|
||||
Boolean result = false;
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
|
@ -1290,7 +1338,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
private Boolean inComponent(String path, ConceptSetComponent vsi, int vsiIndex, String system, String version, String code, boolean only, ValidationProcessInfo info) throws FHIRException {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("inComponent "+vsiIndex);
|
||||
boolean ok = true;
|
||||
|
||||
if (vsi.hasValueSet()) {
|
||||
|
@ -1339,6 +1387,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
vs.setUrl(valueset.getUrl()+"--"+vsiIndex);
|
||||
vs.setVersion(valueset.getVersion());
|
||||
vs.getCompose().addInclude(vsi);
|
||||
opContext.deadCheck("hit server "+vs.getVersionedUrl());
|
||||
ValidationResult res = context.validateCode(options.withNoClient(), new Coding(system, code, null), vs);
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
|
||||
if (info != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
|
@ -1348,16 +1397,20 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
info.addIssue(makeIssue(IssueSeverity.WARNING, IssueType.UNKNOWN, path, msg, OpIssueCode.NotFound, null));
|
||||
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
||||
if (cc.getCode().equals(code)) {
|
||||
opContext.deadCheck("server true");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
info.setErr(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
|
||||
opContext.deadCheck("server codesystem unsupported");
|
||||
return null;
|
||||
}
|
||||
opContext.deadCheck("server not found");
|
||||
return false;
|
||||
}
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
|
||||
opContext.deadCheck("server no server");
|
||||
throw new NoTerminologyServiceException();
|
||||
}
|
||||
return res.isOk();
|
||||
|
@ -1538,7 +1591,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
|
||||
public boolean validateCodeInConceptList(String code, CodeSystem def, List<ConceptDefinitionComponent> list, AlternateCodesProcessingRules altCodeRules) {
|
||||
opContext.deadCheck();
|
||||
opContext.deadCheck("validateCodeInConceptList");
|
||||
if (def.hasUserData("tx.cs.special")) {
|
||||
return ((SpecialCodeSystem) def.getUserData("tx.cs.special")).findConcept(new Coding().setCode(code)) != null;
|
||||
} else if (def.getCaseSensitive()) {
|
||||
|
|
|
@ -36,6 +36,10 @@ public class PackageHackerR5 {
|
|||
r.hack("http://terminology.hl7.org/CodeSystem/v2-0360-2.3.1", "2.3.1");
|
||||
}
|
||||
|
||||
if ("http://hl7.org/fhir/ValueSet/languages".equals(r.getUrl())) {
|
||||
r.getResource().setExperimental(false);
|
||||
}
|
||||
|
||||
if ("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor".equals(r.getUrl()) && "4.0.1".equals(r.getVersion())) {
|
||||
StructureDefinition sd = (StructureDefinition) r.getResource();
|
||||
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
|
||||
|
|
|
@ -59,7 +59,8 @@ public class FhirLoggingInterceptor implements Interceptor {
|
|||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
if (logger != null) {
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes);
|
||||
long responseTimeInMillis = response.receivedResponseAtMillis() - response.sentRequestAtMillis();
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes, responseTimeInMillis);
|
||||
}
|
||||
|
||||
// Reading byte[] clears body. Need to recreate.
|
||||
|
|
|
@ -44,6 +44,8 @@ import org.w3c.dom.events.MutationEvent;
|
|||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
@ -71,6 +73,22 @@ public class XmlLocationAnnotator extends XMLFilterImpl {
|
|||
((EventTarget) dom).addEventListener("DOMNodeInserted", modListener, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (!name.equals("http://javax.xml.XMLConstants/property/accessExternalDTD")) {
|
||||
super.setProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if (!name.equals("http://javax.xml.XMLConstants/property/accessExternalDTD")) {
|
||||
return null;
|
||||
} else {
|
||||
return super.getProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
super.setDocumentLocator(locator);
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
|||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
|
@ -341,6 +342,7 @@ public class BaseWorkerContextTests {
|
|||
public void testValidateCodingWithValueSetChecker() throws IOException {
|
||||
ValidationOptions validationOptions = new ValidationOptions(FhirPublication.R5).withGuessSystem().withVersionFlexible(false);
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(Utilities.makeUuidUrn());
|
||||
Coding coding = new Coding();
|
||||
|
||||
Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, coding, valueSet, expParameters);
|
||||
|
|
|
@ -172,6 +172,6 @@ class ClientTest {
|
|||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logRequest(Mockito.anyString(), Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
.logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any(), Mockito.anyLong());
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.util.List;
|
|||
public interface ToolingClientLogger {
|
||||
|
||||
void logRequest(String method, String url, List<String> headers, byte[] body);
|
||||
void logResponse(String outcome, List<String> headers, byte[] body);
|
||||
void logResponse(String outcome, List<String> headers, byte[] body, long length);
|
||||
String getLastId();
|
||||
void clearLastId();
|
||||
|
||||
|
|
|
@ -64,9 +64,9 @@ public class ManagedWebAccess {
|
|||
}
|
||||
|
||||
public enum WebAccessPolicy {
|
||||
DIRECT, // open access to the local file system, though access can be restricted only to files under the paths in AllowedPaths
|
||||
MANAGED, // no access except by the FileSystemProxyProvider
|
||||
PROHIBITED, // no access at all to File() services
|
||||
DIRECT, // open access to the web, though access can be restricted only to domains in AllowedDomains
|
||||
MANAGED, // no access except by the IWebAccessor
|
||||
PROHIBITED, // no access at all to the web
|
||||
}
|
||||
|
||||
private static WebAccessPolicy accessPolicy = WebAccessPolicy.DIRECT; // for legacy reasons
|
||||
|
|
|
@ -125,7 +125,7 @@ public abstract class I18nBase {
|
|||
if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
|
||||
message = MessageFormat.format(messages.getString(theMessage).trim(), theMessageArguments);
|
||||
} else {
|
||||
message = MessageFormat.format(messages.getString(theMessage).trim(), null);
|
||||
message = MessageFormat.format(messages.getString(theMessage).trim(), (Object) null);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
|
|
|
@ -18,7 +18,9 @@ public class I18nConstants {
|
|||
public static final String BAD_FILE_PATH_ERROR = "Bad_file_path_error";
|
||||
public static final String BASE_PROFILE__HAS_NO_TYPE = "Base_profile__has_no_type";
|
||||
public static final String BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___ = "Base__Derived_profiles_have_different_types____vs___";
|
||||
public static final String BINDING_ADDITIONAL = "BINDING_ADDITIONAL";
|
||||
public static final String BINDING_ADDITIONAL_D = "BINDING_ADDITIONAL_D";
|
||||
public static final String BINDING_ADDITIONAL_UC = "BINDING_ADDITIONAL_UC";
|
||||
public static final String BINDING_ADDITIONAL_USAGE = "BINDING_ADDITIONAL_USAGE";
|
||||
public static final String BINDING_MAX = "BINDING_MAX";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_CANONICAL = "Bundle_BUNDLE_Entry_Canonical";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_DOCUMENT = "Bundle_BUNDLE_Entry_Document";
|
||||
|
@ -1108,4 +1110,10 @@ public class I18nConstants {
|
|||
public static final String SM_TARGET_TYPE_UNKNOWN = "SM_TARGET_TYPE_UNKNOWN";
|
||||
public static final String XHTML_XHTML_ATTRIBUTE_XML_SPACE = "XHTML_XHTML_ATTRIBUTE_XML_SPACE";
|
||||
public static final String VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS = "VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS";
|
||||
public static final String SD_BASE_EXPERIMENTAL = "SD_BASE_EXPERIMENTAL";
|
||||
public static final String SD_ED_EXPERIMENTAL_BINDING = "SD_ED_EXPERIMENTAL_BINDING";
|
||||
public static final String VALIDATION_NO_EXPERIMENTAL_CONTENT = "VALIDATION_NO_EXPERIMENTAL_CONTENT";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN = "SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT = "SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE = "SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE";
|
||||
}
|
||||
|
|
|
@ -214,6 +214,7 @@ public class RenderingI18nContext extends I18nBase {
|
|||
public static final String DATA_REND_DATA = "DATA_REND_DATA";
|
||||
public static final String DATA_REND_DETAILS = "DATA_REND_DETAILS";
|
||||
public static final String DATA_REND_DETAILS_STATED = "DATA_REND_DETAILS_STATED";
|
||||
public static final String DATA_REND_DETAILS_STATED_ND = "DATA_REND_DETAILS_STATED_ND";
|
||||
public static final String DATA_REND_DICOM = "DATA_REND_DICOM";
|
||||
public static final String DATA_REND_DIM = "DATA_REND_DIM";
|
||||
public static final String DATA_REND_DURATION = "DATA_REND_DURATION";
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -77,12 +78,13 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
|
||||
private final FilesystemPackageCacheManagerLocks locks;
|
||||
|
||||
private final FilesystemPackageCacheManagerLocks.LockParameters lockParameters;
|
||||
|
||||
// When running in testing mode, some packages are provided from the test case repository rather than by the normal means
|
||||
// the PackageProvider is responsible for this. if no package provider is defined, or it declines to handle the package,
|
||||
// then the normal means will be used
|
||||
public interface IPackageProvider {
|
||||
boolean handlesPackage(String id, String version);
|
||||
|
||||
InputStreamWithSrc provide(String id, String version) throws IOException;
|
||||
}
|
||||
|
||||
|
@ -92,6 +94,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
public static final String PACKAGE_VERSION_REGEX_OPT = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+(\\#[A-Za-z0-9\\-\\_]+(\\.[A-Za-z0-9\\-\\_]+)*)?$";
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(FilesystemPackageCacheManager.class);
|
||||
private static final String CACHE_VERSION = "3"; // second version - see wiki page
|
||||
|
||||
@Nonnull
|
||||
private final File cacheFolder;
|
||||
|
||||
|
@ -100,6 +103,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
private final Map<String, String> ciList = new HashMap<>();
|
||||
private JsonArray buildInfo;
|
||||
private boolean suppressErrors;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private boolean minimalMemory;
|
||||
|
@ -113,9 +117,20 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
@Getter
|
||||
private final List<PackageServer> packageServers;
|
||||
|
||||
@With
|
||||
@Getter
|
||||
private final FilesystemPackageCacheManagerLocks.LockParameters lockParameters;
|
||||
|
||||
public Builder() throws IOException {
|
||||
this.cacheFolder = getUserCacheFolder();
|
||||
this.packageServers = getPackageServersFromFHIRSettings();
|
||||
this.lockParameters = null;
|
||||
}
|
||||
|
||||
private Builder(File cacheFolder, List<PackageServer> packageServers, FilesystemPackageCacheManagerLocks.LockParameters lockParameters) {
|
||||
this.cacheFolder = cacheFolder;
|
||||
this.packageServers = packageServers;
|
||||
this.lockParameters = lockParameters;
|
||||
}
|
||||
|
||||
private File getUserCacheFolder() throws IOException {
|
||||
|
@ -143,17 +158,12 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
return PackageServer.getConfiguredServers();
|
||||
}
|
||||
|
||||
private Builder(File cacheFolder, List<PackageServer> packageServers) {
|
||||
this.cacheFolder = cacheFolder;
|
||||
this.packageServers = packageServers;
|
||||
}
|
||||
|
||||
public Builder withCacheFolder(String cacheFolderPath) throws IOException {
|
||||
File cacheFolder = ManagedFileAccess.file(cacheFolderPath);
|
||||
if (!cacheFolder.exists()) {
|
||||
throw new FHIRException("The folder '" + cacheFolder + "' could not be found");
|
||||
}
|
||||
return new Builder(cacheFolder, this.packageServers);
|
||||
return new Builder(cacheFolder, this.packageServers, this.lockParameters);
|
||||
}
|
||||
|
||||
public Builder withSystemCacheFolder() throws IOException {
|
||||
|
@ -163,32 +173,33 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
} else {
|
||||
systemCacheFolder = ManagedFileAccess.file(Utilities.path("/var", "lib", ".fhir", "packages"));
|
||||
}
|
||||
return new Builder(systemCacheFolder, this.packageServers);
|
||||
return new Builder(systemCacheFolder, this.packageServers, this.lockParameters);
|
||||
}
|
||||
|
||||
public Builder withTestingCacheFolder() throws IOException {
|
||||
return new Builder(ManagedFileAccess.file(Utilities.path("[tmp]", ".fhir", "packages")), this.packageServers);
|
||||
return new Builder(ManagedFileAccess.file(Utilities.path("[tmp]", ".fhir", "packages")), this.packageServers, this.lockParameters);
|
||||
}
|
||||
|
||||
public FilesystemPackageCacheManager build() throws IOException {
|
||||
return new FilesystemPackageCacheManager(cacheFolder, packageServers);
|
||||
final FilesystemPackageCacheManagerLocks locks;
|
||||
try {
|
||||
locks = FilesystemPackageCacheManagerLocks.getFilesystemPackageCacheManagerLocks(cacheFolder);
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof IOException) {
|
||||
throw (IOException) e.getCause();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return new FilesystemPackageCacheManager(cacheFolder, packageServers, locks, lockParameters);
|
||||
}
|
||||
}
|
||||
|
||||
private FilesystemPackageCacheManager(@Nonnull File cacheFolder, @Nonnull List<PackageServer> packageServers) throws IOException {
|
||||
private FilesystemPackageCacheManager(@Nonnull File cacheFolder, @Nonnull List<PackageServer> packageServers, @Nonnull FilesystemPackageCacheManagerLocks locks, @Nullable FilesystemPackageCacheManagerLocks.LockParameters lockParameters) throws IOException {
|
||||
super(packageServers);
|
||||
this.cacheFolder = cacheFolder;
|
||||
|
||||
try {
|
||||
this.locks = FilesystemPackageCacheManagerLocks.getFilesystemPackageCacheManagerLocks(cacheFolder);
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof IOException) {
|
||||
throw (IOException) e.getCause();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
this.locks = locks;
|
||||
this.lockParameters = lockParameters;
|
||||
prepareCacheFolder();
|
||||
}
|
||||
|
||||
|
@ -218,11 +229,35 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
createIniFile();
|
||||
}
|
||||
deleteOldTempDirectories();
|
||||
cleanUpCorruptPackages();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Look for .lock files that are not actively held by a process. If found, delete the lock file, and the package
|
||||
referenced.
|
||||
*/
|
||||
protected void cleanUpCorruptPackages() throws IOException {
|
||||
for (File file : Objects.requireNonNull(cacheFolder.listFiles())) {
|
||||
if (file.getName().endsWith(".lock")) {
|
||||
if (locks.getCacheLock().canLockFileBeHeldByThisProcess(file)) {
|
||||
String packageDirectoryName = file.getName().substring(0, file.getName().length() - 5);
|
||||
log("Detected potential incomplete package installed in cache: " + packageDirectoryName + ". Attempting to delete");
|
||||
|
||||
File packageDirectory = ManagedFileAccess.file(Utilities.path(cacheFolder, packageDirectoryName));
|
||||
if (packageDirectory.exists()) {
|
||||
Utilities.clearDirectory(packageDirectory.getAbsolutePath());
|
||||
packageDirectory.delete();
|
||||
}
|
||||
file.delete();
|
||||
log("Deleted potential incomplete package: " + packageDirectoryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean iniFileExists() throws IOException {
|
||||
String iniPath = getPackagesIniPath();
|
||||
File iniFile = ManagedFileAccess.file(iniPath);
|
||||
|
@ -421,7 +456,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}, lockParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,7 +500,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
return null;
|
||||
}
|
||||
return loadPackageInfo(path);
|
||||
});
|
||||
}, lockParameters);
|
||||
if (foundPackage != null) {
|
||||
if (foundPackage.isIndexed()){
|
||||
return foundPackage;
|
||||
|
@ -488,7 +523,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
String path = Utilities.path(cacheFolder, foundPackageFolder);
|
||||
output.checkIndexed(path);
|
||||
return output;
|
||||
});
|
||||
}, lockParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,7 +624,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
|
|||
throw e;
|
||||
}
|
||||
return npmPackage;
|
||||
});
|
||||
}, lockParameters);
|
||||
}
|
||||
|
||||
private void log(String s) {
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package org.hl7.fhir.utilities.npm;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import lombok.With;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -27,9 +32,23 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
|
||||
private final File cacheFolder;
|
||||
|
||||
private final Long lockTimeoutTime;
|
||||
private static final LockParameters lockParameters = new LockParameters();
|
||||
|
||||
private final TimeUnit lockTimeoutTimeUnit;
|
||||
public static class LockParameters {
|
||||
@Getter @With
|
||||
private final long lockTimeoutTime;
|
||||
@Getter @With
|
||||
private final TimeUnit lockTimeoutTimeUnit;
|
||||
|
||||
public LockParameters() {
|
||||
this(60L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public LockParameters(long lockTimeoutTime, TimeUnit lockTimeoutTimeUnit) {
|
||||
this.lockTimeoutTime = lockTimeoutTime;
|
||||
this.lockTimeoutTimeUnit = lockTimeoutTimeUnit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is intended to be used only for testing purposes.
|
||||
|
@ -43,21 +62,9 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
* @throws IOException
|
||||
*/
|
||||
public FilesystemPackageCacheManagerLocks(File cacheFolder) throws IOException {
|
||||
this(cacheFolder, 60L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private FilesystemPackageCacheManagerLocks(File cacheFolder, Long lockTimeoutTime, TimeUnit lockTimeoutTimeUnit) throws IOException {
|
||||
this.cacheFolder = cacheFolder;
|
||||
this.lockTimeoutTime = lockTimeoutTime;
|
||||
this.lockTimeoutTimeUnit = lockTimeoutTimeUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is intended to be used only for testing purposes.
|
||||
*/
|
||||
protected FilesystemPackageCacheManagerLocks withLockTimeout(Long lockTimeoutTime, TimeUnit lockTimeoutTimeUnit) throws IOException {
|
||||
return new FilesystemPackageCacheManagerLocks(cacheFolder, lockTimeoutTime, lockTimeoutTimeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single FilesystemPackageCacheManagerLocks instance for the given cacheFolder.
|
||||
|
@ -102,6 +109,19 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean canLockFileBeHeldByThisProcess(File lockFile) throws IOException {
|
||||
return doWriteWithLock(() -> {
|
||||
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
|
||||
FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
|
||||
if (fileLock != null) {
|
||||
fileLock.release();
|
||||
channel.close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;});
|
||||
}
|
||||
}
|
||||
|
||||
public class PackageLock {
|
||||
|
@ -114,15 +134,43 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
this.lock = lock;
|
||||
}
|
||||
|
||||
private void checkForLockFileWaitForDeleteIfExists(File lockFile) throws IOException {
|
||||
private void checkForLockFileWaitForDeleteIfExists(File lockFile, @Nonnull LockParameters lockParameters) throws IOException {
|
||||
if (!lockFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the file is locked by a process. If it is not, it is likely an incomplete package cache install, and
|
||||
// we should throw an exception.
|
||||
if (lockFile.isFile()) {
|
||||
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
|
||||
FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
|
||||
if (fileLock != null) {
|
||||
fileLock.release();
|
||||
channel.close();
|
||||
throw new IOException("Lock file exists, but is not locked by a process: " + lockFile.getName());
|
||||
}
|
||||
System.out.println("File is locked.");
|
||||
}
|
||||
}
|
||||
try {
|
||||
waitForLockFileDeletion(lockFile, lockParameters);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Thread interrupted while waiting for lock", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Wait for the lock file to be deleted. If the lock file is not deleted within the timeout or if the thread is
|
||||
interrupted, an IOException is thrown.
|
||||
*/
|
||||
private void waitForLockFileDeletion(File lockFile, @Nonnull LockParameters lockParameters) throws IOException, InterruptedException {
|
||||
|
||||
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
||||
Path dir = lockFile.getParentFile().toPath();
|
||||
dir.register(watchService, StandardWatchEventKinds.ENTRY_DELETE);
|
||||
|
||||
WatchKey key = watchService.poll(lockTimeoutTime, lockTimeoutTimeUnit);
|
||||
WatchKey key = watchService.poll(lockParameters.lockTimeoutTime, lockParameters.lockTimeoutTimeUnit);
|
||||
if (key == null) {
|
||||
// It is possible that the lock file is deleted before the watch service is registered, so if we timeout at
|
||||
// this point, we should check if the lock file still exists.
|
||||
|
@ -141,24 +189,33 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
key.reset();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Error reading package.", e);
|
||||
} catch (TimeoutException e) {
|
||||
throw new IOException("Error reading package.", e);
|
||||
throw new IOException("Package cache timed out waiting for lock.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public <T> T doReadWithLock(FilesystemPackageCacheManager.CacheLockFunction<T> f) throws IOException {
|
||||
/**
|
||||
* Wraps the execution of a package read function with the appropriate cache, package, and .lock file locking and
|
||||
* checks.
|
||||
*
|
||||
* @param function The function to execute
|
||||
* @param lockParameters The parameters for the lock
|
||||
* @return The return of the function
|
||||
* @param <T> The return type of the function
|
||||
* @throws IOException If an error occurs while managing locking.
|
||||
*/
|
||||
public <T> T doReadWithLock(FilesystemPackageCacheManager.CacheLockFunction<T> function, @Nullable LockParameters lockParameters) throws IOException {
|
||||
final LockParameters resolvedLockParameters = lockParameters != null ? lockParameters : FilesystemPackageCacheManagerLocks.lockParameters;
|
||||
|
||||
cacheLock.getLock().readLock().lock();
|
||||
lock.readLock().lock();
|
||||
|
||||
checkForLockFileWaitForDeleteIfExists(lockFile);
|
||||
checkForLockFileWaitForDeleteIfExists(lockFile, resolvedLockParameters);
|
||||
|
||||
T result = null;
|
||||
try {
|
||||
result = f.get();
|
||||
result = function.get();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
cacheLock.getLock().readLock().unlock();
|
||||
|
@ -166,35 +223,55 @@ public class FilesystemPackageCacheManagerLocks {
|
|||
return result;
|
||||
}
|
||||
|
||||
public <T> T doWriteWithLock(FilesystemPackageCacheManager.CacheLockFunction<T> f) throws IOException {
|
||||
/**
|
||||
* Wraps the execution of a package write function with the appropriate cache, package, and .lock file locking and
|
||||
* checks.
|
||||
*
|
||||
* @param function The function to execute
|
||||
* @param lockParameters The parameters for the lock
|
||||
* @return The return of the function
|
||||
* @param <T> The return type of the function
|
||||
* @throws IOException If an error occurs while managing locking.
|
||||
*/
|
||||
public <T> T doWriteWithLock(FilesystemPackageCacheManager.CacheLockFunction<T> function, @Nullable LockParameters lockParameters) throws IOException {
|
||||
final LockParameters resolvedLockParameters = lockParameters != null ? lockParameters : FilesystemPackageCacheManagerLocks.lockParameters;
|
||||
|
||||
cacheLock.getLock().writeLock().lock();
|
||||
lock.writeLock().lock();
|
||||
|
||||
if (!lockFile.isFile()) {
|
||||
try {
|
||||
TextFile.stringToFile("", lockFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*TODO Eventually, this logic should exist in a Lockfile class so that it isn't duplicated between the main code and
|
||||
the test code.
|
||||
*/
|
||||
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel()) {
|
||||
FileLock fileLock = null;
|
||||
while (fileLock == null) {
|
||||
fileLock = channel.tryLock(0, Long.MAX_VALUE, true);
|
||||
if (fileLock == null) {
|
||||
Thread.sleep(100); // Wait and retry
|
||||
}
|
||||
|
||||
FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
|
||||
|
||||
if (fileLock == null) {
|
||||
waitForLockFileDeletion(lockFile, resolvedLockParameters);
|
||||
fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
|
||||
}
|
||||
if (fileLock == null) {
|
||||
throw new IOException("Failed to acquire lock on file: " + lockFile.getName());
|
||||
}
|
||||
|
||||
if (!lockFile.isFile()) {
|
||||
final ByteBuffer buff = ByteBuffer.wrap(String.valueOf(ProcessHandle.current().pid()).getBytes(StandardCharsets.UTF_8));
|
||||
channel.write(buff);
|
||||
}
|
||||
T result = null;
|
||||
try {
|
||||
result = f.get();
|
||||
result = function.get();
|
||||
} finally {
|
||||
|
||||
lockFile.renameTo(ManagedFileAccess.file(File.createTempFile(lockFile.getName(), ".lock-renamed").getAbsolutePath()));
|
||||
|
||||
fileLock.release();
|
||||
channel.close();
|
||||
|
||||
if (!lockFile.delete()) {
|
||||
lockFile.deleteOnExit();
|
||||
}
|
||||
|
||||
lock.writeLock().unlock();
|
||||
cacheLock.getLock().writeLock().unlock();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
import org.hl7.fhir.utilities.json.model.JsonArray;
|
||||
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||
|
@ -43,7 +44,44 @@ public class PackageHacker {
|
|||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
|
||||
|
||||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v311/package.tgz", "http://hl7.org/fhir/us/core/STU3.1.1");
|
||||
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
|
||||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
|
||||
|
||||
PackageHacker self = new PackageHacker();
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/1.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/1.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/2.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/2.0.0/hl7.terminology.r4b.tgz");
|
||||
self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/2.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/2.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/3.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/3.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/3.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/3.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/4.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/4.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.2.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.2.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.3.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.3.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.4.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.4.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.5.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.5.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.1/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.1/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.2/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.2/hl7.terminology.r4b.tgz");
|
||||
}
|
||||
|
||||
private void cloneToR4B(String src, String dst) throws IOException {
|
||||
FileInputStream fs = ManagedFileAccess.inStream(src);
|
||||
NpmPackage pck = NpmPackage.fromPackage(fs);
|
||||
System.out.println(nice(pck.getNpm()));
|
||||
JsonObject json = pck.getNpm();
|
||||
String name = json.asString("name");
|
||||
json.remove("name");
|
||||
json.add("name", name.replace(".r4", ".r4b"));
|
||||
json.remove("fhirVersions");
|
||||
json.remove("dependencies");
|
||||
JsonArray fv = new JsonArray();
|
||||
json.add("fhirVersions", fv);
|
||||
fv.add("4.3.0");
|
||||
JsonObject dep = new JsonObject();
|
||||
json.add("dependencies", dep);
|
||||
dep.add(VersionUtilities.packageForVersion("4.3.0"), "4.3.0");
|
||||
pck.save(new FileOutputStream(dst));
|
||||
}
|
||||
|
||||
// private void massEdit(File dir) throws IOException {
|
||||
|
|
|
@ -33,7 +33,7 @@ public class CacheVerificationLogger implements ToolingClientLogger {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body) {
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body, long start) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -104,4 +104,9 @@ public interface IXMLWriter {
|
|||
public abstract void link(String href);
|
||||
public abstract void anchor(String name);
|
||||
public abstract void externalLink(String ref) throws IOException;
|
||||
|
||||
// this is only implemented by an implementation that is producing an xhtml representation and handles ellipsing elements
|
||||
public abstract boolean canElide();
|
||||
public abstract void elide() throws IOException;
|
||||
public abstract void attributeElide();
|
||||
}
|
|
@ -912,5 +912,17 @@ public class XMLWriter extends OutputStreamWriter implements IXMLWriter {
|
|||
// ignore this
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canElide() { return false; }
|
||||
|
||||
@Override
|
||||
public void attributeElide() {
|
||||
// ignore this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elide() throws IOException {
|
||||
// ignore this
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,9 @@ Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_ = Attempt to a sli
|
|||
Attempt_to_replace_element_name_for_a_nonchoice_type=Attempt to replace element name for a non-choice type
|
||||
Attempt_to_use_Terminology_server_when_no_Terminology_server_is_available = Attempt to use Terminology server when no Terminology server is available
|
||||
Attempt_to_use_a_snapshot_on_profile__as__before_it_is_generated = Attempt to use a snapshot on profile ''{0}'' as {1} before it is generated
|
||||
BINDING_ADDITIONAL = {0} specified in an additional binding
|
||||
BINDING_ADDITIONAL_D = {0} specified in an additional binding
|
||||
BINDING_ADDITIONAL_UC = {0} specified in an additional binding which applies because {1}
|
||||
BINDING_ADDITIONAL_USAGE = {0} = {1}
|
||||
BINDING_MAX = {0} specified in the max binding
|
||||
BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE = Found {0} matches for ''{1}'' in the bundle ({2})
|
||||
BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE_FRAGMENT = Found {0} matches for fragment {2} in resource ''{1}'' in the bundle ({3})
|
||||
|
@ -1029,7 +1031,7 @@ VALUESET_SUPPLEMENT_MISSING_one = Required supplement not found: {1}
|
|||
VALUESET_SUPPLEMENT_MISSING_other = Required supplements not found: {1}
|
||||
VALUESET_TOO_COSTLY = The value set ''{0}'' expansion has too many codes to display ({1})
|
||||
VALUESET_TOO_COSTLY_COUNT = The value set ''{0}'' expansion has {2} codes, which is too many to display ({1})
|
||||
VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' expansion took too long to process (>{1}sec)
|
||||
VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' {2} took too long to process (>{1}sec)
|
||||
VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
|
||||
VALUESET_UNC_SYSTEM_WARNING_VER = Unknown System/Version ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
|
||||
VALUESET_UNKNOWN_FILTER_PROPERTY = The property ''{0}'' is not known for the system ''{1}'', so may not be understood by the terminology ecosystem. Known properties for this system: {2}
|
||||
|
@ -1138,6 +1140,12 @@ TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF = Hyperlink scheme ''{3}'' in ''{0}''
|
|||
SM_TARGET_TYPE_UNKNOWN = The type of the target variable is not known: {0}
|
||||
XHTML_XHTML_ATTRIBUTE_XML_SPACE = The attribute 'xml:space' is legal but has a fixed value of 'preserve'. It''s use is discouraged
|
||||
VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS = This resource has more than workgroup extension (http://hl7.org/fhir/StructureDefinition/structuredefinition-wg)
|
||||
NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG = Wrong Display Name ''{0}'' for {1}#{2}. There are no valid display names found for language(s) ''{3}''. Default display is ''{4}''
|
||||
NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_OK = There are no valid display names found for the code {1}#{2} for language(s) ''{3}''. The display is ''{4}'' the default language display
|
||||
NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR = Wrong Display Name ''{0}'' for {1}#{2}. There are no valid display names found for language(s) ''{3}''. Default display is ''{4}''
|
||||
NO_VALID_DISPLAY_AT_ALL = Cannot validate display Name ''{0}'' for {1}#{2}: No displays are known
|
||||
|
||||
SD_BASE_EXPERIMENTAL = The definition builds on ''{0}'' which is experimental, but this definition is not labeled as experimental
|
||||
SD_ED_EXPERIMENTAL_BINDING = The definition for the element ''{0}'' binds to the value set ''{1}'' which is experimental, but this structure is not labeled as experimental
|
||||
VALIDATION_NO_EXPERIMENTAL_CONTENT = Experimental content is not allowed in this context
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN = The Usage Context {0}#{1} is not recognised and may not be correct
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT = The Usage Context {0}#{1} is a reference to an element that does not exist
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE = The Usage Context value must be of type {1} not {0}
|
||||
|
|
|
@ -207,7 +207,8 @@ DATA_REND_COND = Condition
|
|||
DATA_REND_COUNT = Count {0}
|
||||
DATA_REND_DATA = Data: {0}
|
||||
DATA_REND_DETAILS = (Details: {0} code
|
||||
DATA_REND_DETAILS_STATED = (Details: {0} code {1} {2} {3} '', stated as '' {4} {5}
|
||||
DATA_REND_DETAILS_STATED = (Details: {0} code {1} = ''{2}'')
|
||||
DATA_REND_DETAILS_STATED_ND = (Details: {0} code {1})
|
||||
DATA_REND_DICOM = DICOM
|
||||
DATA_REND_DIM = Dimensions: {0}
|
||||
DATA_REND_DURATION = Duration {0}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.hl7.fhir.utilities.npm;
|
||||
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -12,10 +12,12 @@ import java.nio.file.Path;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class FilesystemPackageManagerLockTests {
|
||||
|
@ -49,13 +51,13 @@ public class FilesystemPackageManagerLockTests {
|
|||
packageLock.doWriteWithLock(() -> {
|
||||
assertThat(packageLock.getLockFile()).exists();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
assertThat(packageLock.getLockFile()).doesNotExist();
|
||||
|
||||
packageLock.doReadWithLock(() -> {
|
||||
assertThat(packageLock.getLockFile()).doesNotExist();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
}
|
||||
|
||||
@Test void testNoPackageWriteOrReadWhileWholeCacheIsLocked() throws IOException, InterruptedException {
|
||||
|
@ -87,7 +89,7 @@ public class FilesystemPackageManagerLockTests {
|
|||
packageLock.doWriteWithLock(() -> {
|
||||
assertThat(cacheLockFinished.get()).isTrue();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ public class FilesystemPackageManagerLockTests {
|
|||
packageLock.doReadWithLock(() -> {
|
||||
assertThat(cacheLockFinished.get()).isTrue();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -116,6 +118,23 @@ public class FilesystemPackageManagerLockTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Test void testWhenLockIsntHeld_canLockFileBeHeldByThisProcessIsTrue() throws IOException {
|
||||
File lockFile = getPackageLockFile();
|
||||
lockFile.createNewFile();
|
||||
Assertions.assertTrue(filesystemPackageCacheLockManager.getCacheLock().canLockFileBeHeldByThisProcess(lockFile));
|
||||
}
|
||||
|
||||
@Test void testWhenLockIsHelp_canLockFileBeHeldByThisProcessIsFalse() throws InterruptedException, TimeoutException, IOException {
|
||||
File lockFile = getPackageLockFile();
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(cachePath, DUMMY_PACKAGE + ".lock", 2);
|
||||
|
||||
LockfileTestUtility.waitForLockfileCreation(cacheDirectory.getAbsolutePath(), DUMMY_PACKAGE + ".lock");
|
||||
|
||||
Assertions.assertFalse(filesystemPackageCacheLockManager.getCacheLock().canLockFileBeHeldByThisProcess(lockFile));
|
||||
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
@Test void testSinglePackageWriteMultiPackageRead() throws IOException {
|
||||
final FilesystemPackageCacheManagerLocks.PackageLock packageLock = filesystemPackageCacheLockManager.getPackageLock(DUMMY_PACKAGE);
|
||||
AtomicInteger writeCounter = new AtomicInteger(0);
|
||||
|
@ -133,7 +152,7 @@ public class FilesystemPackageManagerLockTests {
|
|||
assertThat(writeCount).isEqualTo(1);
|
||||
writeCounter.decrementAndGet();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -156,7 +175,7 @@ public class FilesystemPackageManagerLockTests {
|
|||
}
|
||||
readCounter.decrementAndGet();
|
||||
return null;
|
||||
});
|
||||
}, null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -179,49 +198,47 @@ public class FilesystemPackageManagerLockTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReadWhenLockedByFileTimesOut() throws IOException {
|
||||
FilesystemPackageCacheManagerLocks shorterTimeoutManager = filesystemPackageCacheLockManager.withLockTimeout(3L, TimeUnit.SECONDS);
|
||||
public void testReadWhenLockedByFileTimesOut() throws InterruptedException, TimeoutException, IOException {
|
||||
FilesystemPackageCacheManagerLocks shorterTimeoutManager = filesystemPackageCacheLockManager;
|
||||
final FilesystemPackageCacheManagerLocks.PackageLock packageLock = shorterTimeoutManager.getPackageLock(DUMMY_PACKAGE);
|
||||
File lockFile = createPackageLockFile();
|
||||
File lockFile = getPackageLockFile();
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(cachePath, lockFile.getName(), 5);
|
||||
LockfileTestUtility.waitForLockfileCreation(cachePath,lockFile.getName());
|
||||
|
||||
Exception exception = assertThrows(IOException.class, () -> {
|
||||
packageLock.doReadWithLock(() -> {
|
||||
assertThat(lockFile).exists();
|
||||
return null;
|
||||
});
|
||||
}, new FilesystemPackageCacheManagerLocks.LockParameters(3L, TimeUnit.SECONDS));
|
||||
});
|
||||
|
||||
assertThat(exception.getMessage()).contains("Error reading package");
|
||||
assertThat(exception.getMessage()).contains("Package cache timed out waiting for lock");
|
||||
assertThat(exception.getCause().getMessage()).contains("Timeout waiting for lock file deletion: " + lockFile.getName());
|
||||
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWhenLockFileIsDeleted() throws IOException {
|
||||
FilesystemPackageCacheManagerLocks shorterTimeoutManager = filesystemPackageCacheLockManager.withLockTimeout(5L, TimeUnit.SECONDS);
|
||||
final FilesystemPackageCacheManagerLocks.PackageLock packageLock = shorterTimeoutManager.getPackageLock(DUMMY_PACKAGE);
|
||||
File lockFile = createPackageLockFile();
|
||||
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
lockFile.delete();
|
||||
});
|
||||
t.start();
|
||||
@Test
|
||||
public void testReadWhenLockFileIsDeleted() throws InterruptedException, TimeoutException, IOException {
|
||||
|
||||
final FilesystemPackageCacheManagerLocks.PackageLock packageLock = filesystemPackageCacheLockManager.getPackageLock(DUMMY_PACKAGE);
|
||||
|
||||
final File lockFile = getPackageLockFile();
|
||||
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(cachePath, lockFile.getName(), 5);
|
||||
LockfileTestUtility.waitForLockfileCreation(cachePath,lockFile.getName());
|
||||
|
||||
packageLock.doReadWithLock(() -> {
|
||||
assertThat(lockFile).doesNotExist();
|
||||
return null;
|
||||
});
|
||||
}, new FilesystemPackageCacheManagerLocks.LockParameters(10L, TimeUnit.SECONDS));
|
||||
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
private File createPackageLockFile() throws IOException {
|
||||
File lockFile = Path.of(cachePath, DUMMY_PACKAGE + ".lock").toFile();
|
||||
TextFile.stringToFile("", lockFile);
|
||||
return lockFile;
|
||||
private File getPackageLockFile() {
|
||||
return Path.of(cachePath, DUMMY_PACKAGE + ".lock").toFile();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.hl7.fhir.utilities.npm;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -13,6 +14,8 @@ import java.util.List;
|
|||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -20,6 +23,7 @@ import javax.annotation.Nonnull;
|
|||
|
||||
import org.hl7.fhir.utilities.IniFile;
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
|
@ -113,6 +117,97 @@ public class FilesystemPackageManagerTests {
|
|||
assertEquals( System.getenv("ProgramData") + "\\.fhir\\packages", folder.getAbsolutePath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorruptPackageCleanup() throws IOException {
|
||||
File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest"));
|
||||
|
||||
File dummyPackage = createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3");
|
||||
File dummyLockFile = createDummyLockFile(cacheDirectory, "example.fhir.uv.myig" , "1.2.3");
|
||||
|
||||
assertThat(dummyPackage).isDirectory();
|
||||
assertThat(dummyPackage).exists();
|
||||
assertThat(dummyLockFile).exists();
|
||||
|
||||
FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build();
|
||||
|
||||
assertThat(dummyPackage).doesNotExist();
|
||||
assertThat(dummyLockFile).doesNotExist();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockedPackageIsntCleanedUp() throws IOException, InterruptedException, TimeoutException {
|
||||
File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest"));
|
||||
|
||||
File dummyPackage = createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3");
|
||||
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(cacheDirectory.getAbsolutePath(), "example.fhir.uv.myig#1.2.3.lock", 2);
|
||||
|
||||
LockfileTestUtility.waitForLockfileCreation(cacheDirectory.getAbsolutePath(), "example.fhir.uv.myig#1.2.3.lock");
|
||||
File dummyLockFile = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "example.fhir.uv.myig#1.2.3.lock");
|
||||
|
||||
assertThat(dummyPackage).isDirectory();
|
||||
assertThat(dummyPackage).exists();
|
||||
assertThat(dummyLockFile).exists();
|
||||
|
||||
FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build();
|
||||
|
||||
assertThat(dummyPackage).exists();
|
||||
assertThat(dummyLockFile).exists();
|
||||
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutForLockedPackageRead() throws IOException, InterruptedException, TimeoutException {
|
||||
String pcmPath = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")).getAbsolutePath();
|
||||
|
||||
final FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder()
|
||||
.withCacheFolder(pcmPath)
|
||||
.withLockParameters(new FilesystemPackageCacheManagerLocks.LockParameters(5,TimeUnit.SECONDS))
|
||||
.build();
|
||||
|
||||
Assertions.assertTrue(pcm.listPackages().isEmpty());
|
||||
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(pcmPath, "example.fhir.uv.myig#1.2.3.lock", 10);
|
||||
File directory = ManagedFileAccess.file(pcmPath, "example.fhir.uv.myig#1.2.3" );
|
||||
directory.mkdir();
|
||||
|
||||
LockfileTestUtility.waitForLockfileCreation(pcmPath, "example.fhir.uv.myig#1.2.3.lock");
|
||||
|
||||
IOException exception = assertThrows(IOException.class, () -> pcm.loadPackageFromCacheOnly("example.fhir.uv.myig", "1.2.3"));
|
||||
|
||||
assertThat(exception.getMessage()).contains("Package cache timed out waiting for lock");
|
||||
assertThat(exception.getCause().getMessage()).contains("Timeout waiting for lock file deletion");
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadFromCacheOnlyWaitsForLockDelete() throws IOException, InterruptedException, TimeoutException {
|
||||
String pcmPath = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")).getAbsolutePath();
|
||||
|
||||
final FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().withCacheFolder(pcmPath).build();
|
||||
|
||||
Assertions.assertTrue(pcm.listPackages().isEmpty());
|
||||
|
||||
pcm.addPackageToCache("example.fhir.uv.myig", "1.2.3", this.getClass().getResourceAsStream("/npm/dummy-package.tgz"), "https://packages.fhir.org/example.fhir.uv.myig/1.2.3");
|
||||
|
||||
String packageAndVersion = "example.fhir.uv.myig#1.2.3";
|
||||
|
||||
//Now sneak in a new lock file and directory:
|
||||
|
||||
File directory = ManagedFileAccess.file(pcmPath, packageAndVersion);
|
||||
directory.mkdir();
|
||||
|
||||
Thread lockThread = LockfileTestProcessUtility.lockWaitAndDeleteInNewProcess(pcmPath, "example.fhir.uv.myig#1.2.3.lock", 5);
|
||||
LockfileTestUtility.waitForLockfileCreation(pcmPath, "example.fhir.uv.myig#1.2.3.lock");
|
||||
|
||||
NpmPackage npmPackage = pcm.loadPackageFromCacheOnly("example.fhir.uv.myig", "1.2.3");
|
||||
|
||||
assertThat(npmPackage.id()).isEqualTo("example.fhir.uv.myig");
|
||||
|
||||
lockThread.join();
|
||||
}
|
||||
|
||||
/**
|
||||
We repeat the same tests multiple times here, in order to catch very rare edge cases.
|
||||
*/
|
||||
|
@ -126,16 +221,16 @@ public class FilesystemPackageManagerTests {
|
|||
return params.stream();
|
||||
}
|
||||
|
||||
private void createDummyTemp(File cacheDirectory, String lowerCase) throws IOException {
|
||||
createDummyPackage(cacheDirectory, lowerCase);
|
||||
private File createDummyTemp(File cacheDirectory, String lowerCase) throws IOException {
|
||||
return createDummyPackage(cacheDirectory, lowerCase);
|
||||
}
|
||||
|
||||
private void createDummyPackage(File cacheDirectory, String packageName, String packageVersion) throws IOException {
|
||||
private File createDummyPackage(File cacheDirectory, String packageName, String packageVersion) throws IOException {
|
||||
String directoryName = packageName + "#" + packageVersion;
|
||||
createDummyPackage(cacheDirectory, directoryName);
|
||||
return createDummyPackage(cacheDirectory, directoryName);
|
||||
}
|
||||
|
||||
private static void createDummyPackage(File cacheDirectory, String directoryName) throws IOException {
|
||||
private static File createDummyPackage(File cacheDirectory, String directoryName) throws IOException {
|
||||
File packageDirectory = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), directoryName);
|
||||
packageDirectory.mkdirs();
|
||||
|
||||
|
@ -144,6 +239,16 @@ public class FilesystemPackageManagerTests {
|
|||
wr.write("Ain't nobody here but us chickens");
|
||||
wr.flush();
|
||||
wr.close();
|
||||
return packageDirectory;
|
||||
}
|
||||
|
||||
private File createDummyLockFile(File cacheDirectory, String packageName, String packageVersion) throws IOException {
|
||||
final File dummyLockFile = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), packageName + "#" + packageVersion + ".lock");
|
||||
final FileWriter wr = new FileWriter(dummyLockFile);
|
||||
wr.write("Ain't nobody here but us chickens");
|
||||
wr.flush();
|
||||
wr.close();
|
||||
return dummyLockFile;
|
||||
}
|
||||
|
||||
private void assertThatDummyTempExists(File cacheDirectory, String dummyTempPackage) throws IOException {
|
||||
|
@ -241,13 +346,13 @@ public class FilesystemPackageManagerTests {
|
|||
@MethodSource("packageCacheMultiThreadTestParams")
|
||||
@ParameterizedTest
|
||||
public void packageCacheMultiThreadTest(final int threadTotal, final int packageCacheManagerTotal) throws IOException {
|
||||
|
||||
String pcmPath = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")).getAbsolutePath();
|
||||
System.out.println("Using temp pcm path: " + pcmPath);
|
||||
FilesystemPackageCacheManager[] packageCacheManagers = new FilesystemPackageCacheManager[packageCacheManagerTotal];
|
||||
Random rand = new Random();
|
||||
|
||||
final AtomicInteger totalSuccessful = new AtomicInteger();
|
||||
final ConcurrentHashMap successfulThreads = new ConcurrentHashMap();
|
||||
final ConcurrentHashMap<Long, Integer> successfulThreads = new ConcurrentHashMap<>();
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
for (int i = 0; i < threadTotal; i++) {
|
||||
final int index = i;
|
||||
|
@ -256,22 +361,27 @@ public class FilesystemPackageManagerTests {
|
|||
System.out.println("Thread #" + index + ": " + Thread.currentThread().getId() + " started");
|
||||
final int randomPCM = rand.nextInt(packageCacheManagerTotal);
|
||||
final int randomOperation = rand.nextInt(4);
|
||||
final String operationName;
|
||||
if (packageCacheManagers[randomPCM] == null) {
|
||||
packageCacheManagers[randomPCM] = new FilesystemPackageCacheManager.Builder().withCacheFolder(pcmPath).build();
|
||||
}
|
||||
FilesystemPackageCacheManager pcm = packageCacheManagers[randomPCM];
|
||||
if (randomOperation == 0) {
|
||||
operationName = "addPackageToCache";
|
||||
pcm.addPackageToCache("example.fhir.uv.myig", "1.2.3", this.getClass().getResourceAsStream("/npm/dummy-package.tgz"), "https://packages.fhir.org/example.fhir.uv.myig/1.2.3");
|
||||
} else if (randomOperation == 1) {
|
||||
operationName = "clear";
|
||||
pcm.clear();
|
||||
} else if (randomOperation == 2) {
|
||||
operationName = "loadPackageFromCacheOnly";
|
||||
pcm.loadPackageFromCacheOnly("example.fhir.uv.myig", "1.2.3");
|
||||
} else {
|
||||
operationName = "removePackage";
|
||||
pcm.removePackage("example.fhir.uv.myig", "1.2.3");
|
||||
}
|
||||
totalSuccessful.incrementAndGet();
|
||||
successfulThreads.put(Thread.currentThread().getId(), index);
|
||||
System.out.println("Thread #" + index + ": " + Thread.currentThread().getId() + " completed");
|
||||
System.out.println("Thread #" + index + ": " + Thread.currentThread().getId() + " completed. Ran: " + operationName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Thread #" + index + ": " + Thread.currentThread().getId() + " failed");
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package org.hl7.fhir.utilities.npm;
|
||||
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* FilesystemPackageCacheManagerLocks relies on the existence of .lock files to prevent access to packages being written
|
||||
* by processes outside the current JVM. Testing this functionality means creating a process outside the JUnit test JVM,
|
||||
* which is achieved by running a separate Java process.
|
||||
* <p/>
|
||||
* Intended usage:
|
||||
* <p/>
|
||||
* The helper method {@link #lockWaitAndDeleteInNewProcess(String, String, int)} is the intended starting point for
|
||||
* using this class.
|
||||
* <p/>
|
||||
*
|
||||
*
|
||||
* This class deliberately avoids using any dependencies outside java.*, which avoids having to construct a classpath
|
||||
* for the separate process.
|
||||
*/
|
||||
public class LockfileTestProcessUtility {
|
||||
/**
|
||||
* Main method to allow running this class.
|
||||
* <p/
|
||||
* It is not recommended to call this method directly. Instead, use the provided {@link #lockWaitAndDeleteInNewProcess(String, String, int)} method.
|
||||
*
|
||||
* @param args The arguments to the main method. The first argument is the path to create the lockfile in, the second
|
||||
* argument is the name of the lockfile, and the third argument is the number of seconds to wait before
|
||||
* deleting the lockfile.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
String path = args[0];
|
||||
String lockFileName = args[1];
|
||||
int seconds = Integer.parseInt(args[2]);
|
||||
|
||||
try {
|
||||
lockWaitAndDelete(path, lockFileName, seconds);
|
||||
} catch (InterruptedException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper method that starts a new process, creates a lock file in the path and waits for a specified number of
|
||||
* seconds before deleting it.
|
||||
* <p/>
|
||||
* This method calls the {@link #main(String[])} method in a new process.
|
||||
*
|
||||
* @param path The path to create the lockfile in
|
||||
* @param lockFileName The name of the lockfile
|
||||
* @param seconds The number of seconds to wait before deleting the lockfile
|
||||
* @return The thread wrapping the process execution. This can be used to wait for the process to complete, so that
|
||||
* System.out and System.err can be processed before tests return results.
|
||||
*/
|
||||
public static Thread lockWaitAndDeleteInNewProcess(String path, String lockFileName, int seconds) {
|
||||
Thread t = new Thread(() -> {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder("java", "-cp", "target/test-classes", LockfileTestProcessUtility.class.getName(), path, lockFileName, Integer.toString(seconds));
|
||||
try {
|
||||
Process process = processBuilder.start();
|
||||
process.getErrorStream().transferTo(System.err);
|
||||
process.getInputStream().transferTo(System.out);
|
||||
process.waitFor();
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual logic to create a .lock file.
|
||||
* <p/>
|
||||
* This should match the logic in FilesystemPackageCacheManagerLocks
|
||||
* <p/>
|
||||
*
|
||||
* @param path The path to create the lockfile in
|
||||
* @param lockFileName The name of the lockfile
|
||||
* @param seconds The number of seconds to wait before deleting the lockfile
|
||||
* @throws InterruptedException If the thread is interrupted while waiting
|
||||
* @throws IOException If there is an error accessing the file system
|
||||
*/
|
||||
/* TODO Eventually, this logic should exist in a Lockfile class so that it isn't duplicated between the main code and
|
||||
the test code.
|
||||
*/
|
||||
private static void lockWaitAndDelete(String path, String lockFileName, int seconds) throws InterruptedException, IOException {
|
||||
|
||||
File lockFile = Paths.get(path,lockFileName).toFile();
|
||||
|
||||
try (FileChannel channel = new RandomAccessFile(lockFile.getAbsolutePath(), "rw").getChannel()) {
|
||||
FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, false);
|
||||
if (fileLock != null) {
|
||||
final ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8));
|
||||
channel.write(buff);
|
||||
System.out.println("File "+lockFileName+" is locked. Waiting for " + seconds + " seconds to release. ");
|
||||
Thread.sleep(seconds * 1000L);
|
||||
|
||||
lockFile.renameTo(ManagedFileAccess.file(File.createTempFile(lockFile.getName(), ".lock-renamed").getAbsolutePath()));
|
||||
|
||||
fileLock.release();
|
||||
channel.close();
|
||||
System.out.println(System.currentTimeMillis());
|
||||
System.out.println("File "+lockFileName+" is released.");
|
||||
|
||||
lockFile.delete();
|
||||
}}finally {
|
||||
if (lockFile.exists()) {
|
||||
lockFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package org.hl7.fhir.utilities.npm;
|
||||
|
||||
|
||||
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
|
||||
import org.apache.commons.io.monitor.FileAlterationMonitor;
|
||||
import org.apache.commons.io.monitor.FileAlterationObserver;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
|
||||
public class LockfileTestUtility {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Wait for the lock file to be created in the given path.
|
||||
* <p/>
|
||||
* Normally, within the same JVM, you could use a CountdownLatch for the same purpose, but since this the lock file is
|
||||
* being created in a separate process, we need to use a mechanism that doesn't rely on shared threads.
|
||||
*
|
||||
* @param path The path containing the lock file
|
||||
* @param lockFileName The name of the lock file
|
||||
* @throws InterruptedException If the thread is interrupted while waiting
|
||||
* @throws TimeoutException If the lock file is not created within 10 seconds
|
||||
*/
|
||||
public static void waitForLockfileCreation(String path, String lockFileName) throws InterruptedException, TimeoutException {
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
FileAlterationMonitor monitor = new FileAlterationMonitor(100);
|
||||
FileAlterationObserver observer = new FileAlterationObserver(path);
|
||||
|
||||
observer.addListener(new FileAlterationListenerAdaptor(){
|
||||
|
||||
@Override
|
||||
public void onStart(FileAlterationObserver observer) {
|
||||
if (Files.exists(Paths.get(path, lockFileName))) {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileCreate(File file) {
|
||||
System.out.println("File created: " + file.getName());
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
monitor.addObserver(observer);
|
||||
|
||||
try {
|
||||
monitor.start();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
boolean success = latch.await(10, TimeUnit.SECONDS);
|
||||
try {
|
||||
monitor.stop();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
throw new TimeoutException("Timed out waiting for lock file creation: " + lockFileName);
|
||||
}
|
||||
// TODO This is a workaround for an edge condition that shows up with testing, where the lock is not reflected in
|
||||
// the file system immediately. It is unlikely to appear in production environments. Should it occur, it will
|
||||
// result in a lock file being erroneously reported as not having an owning process, and will cause a package to
|
||||
// fail to be loaded from that cache until the lock is cleaned up by cache initialization.
|
||||
Thread.sleep(100);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.26-SNAPSHOT</version>
|
||||
<version>6.3.30-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1192,6 +1192,34 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
|
||||
protected int countFragmentMatches(Element element, String fragment, NodeStack stack) {
|
||||
int count = countFragmentMatches(element, fragment);
|
||||
if (count == 0 && element.isResource() && element.hasParentForValidator()) {
|
||||
Element bnd = getElementBundle(element);
|
||||
if (bnd != null) {
|
||||
// in this case, we look into the parent - if there is one - and if it's a bundle, we look at the entries (but not in them)
|
||||
for (Element be : bnd.getChildrenByName("entry")) {
|
||||
String id = be.getIdBase();
|
||||
if (fragment.equals(id)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private Element getElementBundle(Element element) {
|
||||
Element p = element.getParentForValidator();
|
||||
if (p != null) {
|
||||
Element b = p.getParentForValidator();
|
||||
if (b != null && b.fhirType().equals("Bundle")) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int countFragmentMatches(Element element, String fragment) {
|
||||
int count = 0;
|
||||
if (fragment.equals(element.getIdBase())) {
|
||||
|
|
|
@ -227,6 +227,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
@Getter @Setter private boolean checkIPSCodes;
|
||||
@Getter @Setter private BestPracticeWarningLevel bestPracticeLevel;
|
||||
@Getter @Setter private boolean unknownCodeSystemsCauseErrors;
|
||||
@Getter @Setter private boolean noExperimentalContent;
|
||||
@Getter @Setter private Locale locale;
|
||||
@Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>();
|
||||
@Getter @Setter private List<String> extensionDomains = new ArrayList<>();
|
||||
|
@ -909,6 +910,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
validator.setPolicyAdvisor(policyAdvisor);
|
||||
}
|
||||
validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors);
|
||||
validator.setNoExperimentalContent(noExperimentalContent);
|
||||
return validator;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ public class CliContext {
|
|||
private boolean showTimes = false;
|
||||
|
||||
@JsonProperty("locale")
|
||||
private String locale = Locale.ENGLISH.getDisplayLanguage();
|
||||
private String locale = Locale.ENGLISH.toLanguageTag();
|
||||
|
||||
@JsonProperty("locations")
|
||||
private Map<String, String> locations = new HashMap<String, String>();
|
||||
|
@ -166,6 +166,9 @@ public class CliContext {
|
|||
@JsonProperty("unknownCodeSystemsCauseErrors")
|
||||
private boolean unknownCodeSystemsCauseErrors;
|
||||
|
||||
@JsonProperty("noExperimentalContent")
|
||||
private boolean noExperimentalContent;
|
||||
|
||||
@JsonProperty("baseEngine")
|
||||
public String getBaseEngine() {
|
||||
return baseEngine;
|
||||
|
@ -836,6 +839,7 @@ public class CliContext {
|
|||
Objects.equals(bestPracticeLevel, that.bestPracticeLevel) &&
|
||||
Objects.equals(watchScanDelay, that.watchScanDelay) &&
|
||||
Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) &&
|
||||
Objects.equals(noExperimentalContent, that.noExperimentalContent) &&
|
||||
Objects.equals(watchSettleTime, that.watchSettleTime) ;
|
||||
}
|
||||
|
||||
|
@ -844,7 +848,7 @@ public class CliContext {
|
|||
return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
|
||||
noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT,
|
||||
targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars,
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -904,6 +908,7 @@ public class CliContext {
|
|||
", watchSettleTime=" + watchSettleTime +
|
||||
", watchScanDelay=" + watchScanDelay +
|
||||
", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
|
||||
", noExperimentalContent=" + noExperimentalContent +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -973,5 +978,16 @@ public class CliContext {
|
|||
this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
|
||||
}
|
||||
|
||||
@JsonProperty("noExperimentalContent")
|
||||
public boolean isNoExperimentalContent() {
|
||||
return noExperimentalContent;
|
||||
}
|
||||
|
||||
|
||||
@JsonProperty("noExperimentalContent")
|
||||
public void setNoExperimentalContent(boolean noExperimentalContent) {
|
||||
this.noExperimentalContent = noExperimentalContent;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -529,14 +529,18 @@ public class ValidationService {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
protected ValidationEngine buildValidationEngine( CliContext cliContext, String definitions, TimeTracker timeTracker) throws IOException, URISyntaxException {
|
||||
protected ValidationEngine buildValidationEngine(CliContext cliContext, String definitions, TimeTracker timeTracker) throws IOException, URISyntaxException {
|
||||
System.out.print(" Load FHIR v" + cliContext.getSv() + " from " + definitions);
|
||||
ValidationEngine validationEngine = getValidationEngineBuilder().withTHO(false).withVersion(cliContext.getSv()).withTimeTracker(timeTracker).withUserAgent(Common.getValidatorUserAgent()).fromSource(definitions);
|
||||
|
||||
System.out.println(" - " + validationEngine.getContext().countAllCaches() + " resources (" + timeTracker.milestone() + ")");
|
||||
|
||||
loadIgsAndExtensions(validationEngine, cliContext, timeTracker);
|
||||
if (validationEngine.getContext().getTxCache() == null) {
|
||||
if (cliContext.getTxCache() != null) {
|
||||
TerminologyCache cache = new TerminologyCache(new Object(), cliContext.getTxCache());
|
||||
validationEngine.getContext().initTxCache(cache);
|
||||
}
|
||||
if (validationEngine.getContext().getTxCache() == null || validationEngine.getContext().getTxCache().getFolder() == null) {
|
||||
System.out.println(" No Terminology Cache");
|
||||
} else {
|
||||
System.out.println(" Terminology Cache at "+validationEngine.getContext().getTxCache().getFolder());
|
||||
|
@ -582,6 +586,7 @@ public class ValidationService {
|
|||
validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
|
||||
validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
|
||||
validationEngine.setUnknownCodeSystemsCauseErrors(cliContext.isUnknownCodeSystemsCauseErrors());
|
||||
validationEngine.setNoExperimentalContent(cliContext.isNoExperimentalContent());
|
||||
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
|
||||
validationEngine.prepare(); // generate any missing snapshots
|
||||
System.out.println(" go (" + timeTracker.milestone() + ")");
|
||||
|
|
|
@ -95,6 +95,7 @@ public class Params {
|
|||
public static final String CHECK_IPS_CODES = "-check-ips-codes";
|
||||
public static final String BEST_PRACTICE = "-best-practice";
|
||||
public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors";
|
||||
public static final String NO_EXPERIMENTAL_CONTENT = "-no-experimental-content";
|
||||
|
||||
public static final String RUN_TESTS = "-run-tests";
|
||||
|
||||
|
@ -321,6 +322,8 @@ public class Params {
|
|||
cliContext.setForPublication(true);
|
||||
} else if (args[i].equals(UNKNOWN_CODESYSTEMS_CAUSE_ERROR)) {
|
||||
cliContext.setUnknownCodeSystemsCauseErrors(true);
|
||||
} else if (args[i].equals(NO_EXPERIMENTAL_CONTENT)) {
|
||||
cliContext.setNoExperimentalContent(true);
|
||||
} else if (args[i].equals(VERBOSE)) {
|
||||
cliContext.setCrumbTrails(true);
|
||||
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {
|
||||
|
|
|
@ -217,6 +217,7 @@ import org.hl7.fhir.validation.instance.type.ValueSetValidator;
|
|||
import org.hl7.fhir.validation.instance.utils.*;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
|
||||
/**
|
||||
* Thinking of using this in a java program? Don't!
|
||||
* You should use one of the wrappers instead. Either in HAPI, or use ValidationEngine
|
||||
|
@ -599,6 +600,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private IDigitalSignatureServices signatureServices;
|
||||
private ContextUtilities cu;
|
||||
private boolean unknownCodeSystemsCauseErrors;
|
||||
private boolean noExperimentalContent;
|
||||
|
||||
public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) {
|
||||
super(theContext, xverManager, false);
|
||||
|
@ -1355,19 +1357,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension maxVS = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, maxVS, true);
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, maxVS, true, null);
|
||||
// } else if (binding.hasValueSet()) {
|
||||
// hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
} else if (!noBindingMsgSuppressed) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, null, false) && checkDisp;
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, null, false, b.toString()) && checkDisp;
|
||||
}
|
||||
}
|
||||
} catch (CheckCodeOnServerException e) {
|
||||
|
@ -1393,25 +1396,186 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return checkDisp;
|
||||
}
|
||||
|
||||
private boolean isInScope(ElementDefinitionBindingAdditionalComponent ab) {
|
||||
private boolean isInScope(ElementDefinitionBindingAdditionalComponent ab, StructureDefinition profile, Element resource, StringBuilder b) {
|
||||
if (ab.getUsage().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
boolean ok = true;
|
||||
for (UsageContext usage : ab.getUsage()) {
|
||||
if (isInScope(usage)) {
|
||||
if (!isInScope(usage, profile, resource, b)) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean isInScope(UsageContext usage, StructureDefinition profile, Element resource, StringBuilder b) {
|
||||
if (isKnownUsage(usage)) {
|
||||
return true;
|
||||
}
|
||||
if (usage.getCode().hasSystem() && (usage.getCode().getSystem().equals(profile.getUrl()) || usage.getCode().getSystem().equals(profile.getVersionedUrl()))) {
|
||||
// if it's not a defined usage from external sources, it might match something in the data content
|
||||
List<Element> items = findDataValue(resource, usage.getCode().getCode());
|
||||
if (matchesUsage(items, usage.getValue())) {
|
||||
b.append(context.formatMessage(I18nConstants.BINDING_ADDITIONAL_USAGE, displayCoding(usage.getCode()), display(usage.getValue())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ab.getUsage().isEmpty();
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInScope(UsageContext usage) {
|
||||
if (isKnownUsage(usage)) {
|
||||
private String displayCoding(Coding value) {
|
||||
return value.getCode();
|
||||
}
|
||||
|
||||
private String displayCodeableConcept(CodeableConcept value) {
|
||||
for (Coding c : value.getCoding()) {
|
||||
String s = displayCoding(c);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return value.getText();
|
||||
}
|
||||
|
||||
private String display(DataType value) {
|
||||
switch (value.fhirType()) {
|
||||
case "Coding" : return displayCoding((Coding) value);
|
||||
case "CodeableConcept" : return displayCodeableConcept((CodeableConcept) value);
|
||||
}
|
||||
return value.fhirType();
|
||||
}
|
||||
|
||||
private boolean matchesUsage(List<Element> items, DataType value) {
|
||||
for (Element item : items) {
|
||||
if (matchesUsage(item, value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String display(List<Element> items) {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (Element item : items) {
|
||||
display(b, item);
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private void display(CommaSeparatedStringBuilder b, Element item) {
|
||||
if (item.isPrimitive()) {
|
||||
b.append(item.primitiveValue());
|
||||
} else if (item.fhirType().equals("CodeableConcept")) {
|
||||
for (Element c : item.getChildren("coding")) {
|
||||
b.append(c.getNamedChildValue("code"));
|
||||
}
|
||||
} else {
|
||||
b.append(item.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean matchesUsage(Element item, DataType value) {
|
||||
switch (value.fhirType()) {
|
||||
case "CodeableConcept": return matchesUsageCodeableConcept(item, (CodeableConcept) value);
|
||||
case "Quantity": return false;
|
||||
case "Range": return false;
|
||||
case "Reference": return false;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConcept(Element item, CodeableConcept value) {
|
||||
switch (item.fhirType()) {
|
||||
case "CodeableConcept": return matchesUsageCodeableConceptCodeableConcept(item, value);
|
||||
case "Coding": return matchesUsageCodeableConceptCoding(item, value);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConceptCoding(Element item, CodeableConcept value) {
|
||||
String system = item.getNamedChildValue("system");
|
||||
String version = item.getNamedChildValue("version");
|
||||
String code = item.getNamedChildValue("code");
|
||||
for (Coding c : value.getCoding()) {
|
||||
if (system == null || !system.equals(c.getSystem())) {
|
||||
return false;
|
||||
}
|
||||
if (code == null || !code.equals(c.getCode())) {
|
||||
return false;
|
||||
}
|
||||
if (c.hasVersion()) {
|
||||
if (version == null || !version.equals(c.getVersion())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConceptCodeableConcept(Element item, CodeableConcept value) {
|
||||
for (Element code : item.getChildren("coding")) {
|
||||
if (matchesUsageCodeableConceptCoding(code, value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Element> findDataValue(Element resource, String code) {
|
||||
List<Element> items = new ArrayList<Element>();
|
||||
if (resource != null) {
|
||||
findDataValues(items, resource, code);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private void findDataValues(List<Element> items, Element element, String path) {
|
||||
if (element.getPath() == null) {
|
||||
return;
|
||||
}
|
||||
if (pathMatches(element.getPath(), path)) {
|
||||
items.add(element);
|
||||
} else if (element.hasChildren() && path.startsWith(element.getPath())) {
|
||||
for (Element child : element.getChildren()) {
|
||||
findDataValues(items, child, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean pathMatches(String actualPath, String pathSpec) {
|
||||
String[] ap = actualPath.split("\\.");
|
||||
String[] ps = pathSpec.split("\\.");
|
||||
if (ap.length != ps.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ap.length; i++) {
|
||||
if (!pathSegmentMatches(ap[i], ps[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean pathSegmentMatches(String ap, String ps) {
|
||||
if (ps.contains("[")) {
|
||||
return ap.equals(ps);
|
||||
} else {
|
||||
if (ap.contains("[")) {
|
||||
ap = ap.substring(0, ap.indexOf("["));
|
||||
}
|
||||
return ap.equals(ps);
|
||||
}
|
||||
}
|
||||
|
||||
private BindingStrength convertPurposeToStrength(AdditionalBindingPurposeVS purpose) {
|
||||
switch (purpose) {
|
||||
case MAXIMUM: return BindingStrength.REQUIRED;
|
||||
case EXTENSIBLE: return BindingStrength.EXTENSIBLE;
|
||||
case PREFERRED: return BindingStrength.PREFERRED;
|
||||
case REQUIRED: return BindingStrength.REQUIRED;
|
||||
default: return null;
|
||||
|
@ -1423,7 +1587,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private boolean validateBindingCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, NodeStack stack, BooleanHolder bh, boolean checkDisp, BooleanHolder checked,
|
||||
CodeableConcept cc, String vsRef, ValueSet valueset, BindingStrength strength, Extension maxVS, boolean base) throws CheckCodeOnServerException {
|
||||
CodeableConcept cc, String vsRef, ValueSet valueset, BindingStrength strength, Extension maxVS, boolean base, String usageNote) throws CheckCodeOnServerException {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -1435,12 +1599,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingContext bc = base ? BindingContext.BASE : BindingContext.ADDITIONAL;
|
||||
if (!cc.hasCoding()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET, describeReference(vsRef, valueset, bc)));
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET, describeReference(vsRef, valueset, bc, usageNote)));
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (maxVS != null)
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESETMAX, describeReference(ToolingExtensions.readStringFromExtension(maxVS)), valueset.getVersionedUrl()));
|
||||
else if (!noExtensibleWarnings) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET_EXT, describeReference(vsRef, valueset, bc));
|
||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET_EXT, describeReference(vsRef, valueset, bc, usageNote));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1490,17 +1654,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
} else if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
// we've already handled the warnings / errors about this, and set the status correctly. We don't need to do anything more?
|
||||
} else {
|
||||
} else if (vr.getErrorClass() != TerminologyServiceErrorClass.SERVER_ERROR) { // (should have?) already handled server error
|
||||
if (strength == BindingStrength.REQUIRED) {
|
||||
bh.see(txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(vsRef, valueset, bc), ccSummary(cc)));
|
||||
bh.see(txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc)));
|
||||
} else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (maxVS != null)
|
||||
bh.see(checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(maxVS), cc, stack));
|
||||
if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(vsRef, valueset, bc), ccSummary(cc));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc));
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(vsRef, valueset, bc), ccSummary(cc));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1647,7 +1811,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, vsMax, true);
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, vsMax, true, null);
|
||||
|
||||
// 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")) {
|
||||
|
@ -1659,11 +1823,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, null, false);
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, null, false, b.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1697,18 +1862,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, vsMax, true);
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, vsMax, true, null);
|
||||
} else if (binding.hasValueSet()) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
} else if (!inCodeableConcept && !noBindingMsgSuppressed) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, null, true) && ok;
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, null, true, b.toString()) && ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1727,7 +1893,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
private boolean validateBindingTerminologyCoding(List<ValidationMessage> errors, String path, Element element,
|
||||
StructureDefinition profile, NodeStack stack, boolean ok, Coding c, String code, String system, String display,
|
||||
String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base) {
|
||||
String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base, String usageNote) {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -1753,27 +1919,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
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()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc), 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(vsRef, valueset, bc, usageNote), vr.getMessage(), system+"#"+code);
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc, usageNote));
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc, usageNote));
|
||||
}
|
||||
}
|
||||
} else if (strength == BindingStrength.REQUIRED)
|
||||
ok= txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_4, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code) && ok;
|
||||
ok= txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_4, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack) && ok;
|
||||
else
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_5, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_5, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_6, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_6, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null){
|
||||
|
@ -1895,9 +2061,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+cc.toString());
|
||||
if (!vr.isOk()) {
|
||||
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_7, describeReference(maxVSUrl, valueset, BindingContext.MAXVS), vr.getMessage());
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_7, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), vr.getMessage());
|
||||
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, BindingContext.MAXVS), 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, BindingContext.MAXVS, null), ccSummary(cc)) && ok;
|
||||
}
|
||||
} catch (CheckCodeOnServerException e) {
|
||||
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||
|
@ -1935,9 +2101,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
|
||||
if (!vr.isOk()) {
|
||||
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, BindingContext.MAXVS), vr.getMessage(), c.getSystem()+"#"+c.getCode());
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), vr.getMessage(), c.getSystem()+"#"+c.getCode());
|
||||
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, BindingContext.MAXVS), 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, BindingContext.MAXVS, null), c.getSystem(), c.getCode()) && ok;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) e.printStackTrace();
|
||||
|
@ -1965,9 +2131,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+value);
|
||||
if (!vr.isOk()) {
|
||||
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, BindingContext.BASE), vr.getMessage(), value);
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.BASE, null), vr.getMessage(), value);
|
||||
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, BindingContext.BASE), 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, BindingContext.BASE, null), vr.getMessage()) && ok;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -2028,7 +2194,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, vsMax, true);
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, vsMax, true, null);
|
||||
// } else if (binding.hasValueSet()) {
|
||||
// hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
|
||||
|
@ -2037,12 +2203,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, null, false) && ok;
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, null, false, b.toString()) && ok;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -2067,9 +2234,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return ok;
|
||||
}
|
||||
|
||||
private Element getResource(NodeStack stack) {
|
||||
if (stack.getElement().isResource()) {
|
||||
return stack.getElement();
|
||||
}
|
||||
if (stack.getParent() == null) {
|
||||
return null;
|
||||
}
|
||||
return getResource(stack.getParent());
|
||||
}
|
||||
|
||||
private boolean validateBindingCodedElement(List<ValidationMessage> errors, String path, Element element,
|
||||
StructureDefinition profile, NodeStack stack, String theCode, String theSystem, boolean ok, BooleanHolder checked,
|
||||
Coding c, String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base) {
|
||||
Coding c, String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base, String usageNote) {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -2097,28 +2274,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
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()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc), 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(vsRef, valueset, bc, usageNote), vr.getMessage(), theSystem+"#"+theCode) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc), theSystem+"#"+theCode);
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc, usageNote), theSystem+"#"+theCode);
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc), theSystem+"#"+theCode);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc, usageNote), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (strength == BindingStrength.REQUIRED)
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_12, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_12, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack) && ok;
|
||||
else if (!noExtensibleWarnings) {
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_13, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), c.getSystem()+"#"+c.getCode());
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_13, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), c.getSystem()+"#"+c.getCode());
|
||||
}
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null) {
|
||||
|
@ -3016,7 +3193,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// check that no illegal elements and attributes have been used
|
||||
ok = checkInnerNames(errors, e, path, xhtml.getChildNodes(), false) && ok;
|
||||
ok = checkUrls(errors, e, path, xhtml.getChildNodes()) && ok;
|
||||
ok = checkIdRefs(errors, e, path, xhtml, resource) && ok;
|
||||
ok = checkIdRefs(errors, e, path, xhtml, resource, node) && ok;
|
||||
if (true) {
|
||||
ok = checkReferences(valContext, errors, e, path, "div", xhtml, resource) && ok;
|
||||
}
|
||||
|
@ -3465,11 +3642,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return ok;
|
||||
}
|
||||
|
||||
private boolean checkIdRefs(List<ValidationMessage> errors, Element e, String path, XhtmlNode node, Element resource) {
|
||||
private boolean checkIdRefs(List<ValidationMessage> errors, Element e, String path, XhtmlNode node, Element resource, NodeStack stack) {
|
||||
boolean ok = true;
|
||||
if (node.getNodeType() == NodeType.Element && node.getAttribute("idref") != null) {
|
||||
String idref = node.getAttribute("idref");
|
||||
int count = countFragmentMatches(resource, idref);
|
||||
int count = countFragmentMatches(resource, idref, stack);
|
||||
if (count == 0) {
|
||||
ok = warning(errors, "2023-12-01", IssueType.INVALID, e.line(), e.col(), path, idref == null, I18nConstants.XHTML_IDREF_NOT_FOUND, idref) && ok;
|
||||
} else if (count > 1) {
|
||||
|
@ -3478,7 +3655,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
if (node.hasChildren()) {
|
||||
for (XhtmlNode child : node.getChildNodes()) {
|
||||
checkIdRefs(errors, e, path, child, resource);
|
||||
checkIdRefs(errors, e, path, child, resource, stack);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
|
@ -3562,15 +3739,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} 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, vr.getMessage());
|
||||
} 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, BindingContext.BASE), 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, BindingContext.BASE, null), getErrorMessage(vr.getMessage())) && ok;
|
||||
} else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET))
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), value, stack) && ok;
|
||||
else if (!noExtensibleWarnings && !isOkExtension(value, vs))
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_17, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE), getErrorMessage(vr.getMessage()));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_17, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE, null), getErrorMessage(vr.getMessage()));
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_18, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE), getErrorMessage(vr.getMessage()));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_18, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE, null), getErrorMessage(vr.getMessage()));
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null){
|
||||
|
@ -4278,7 +4455,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return false;
|
||||
}
|
||||
|
||||
private String describeReference(String reference, CanonicalResource target, BindingContext ctxt) {
|
||||
private String describeReference(String reference, CanonicalResource target, BindingContext ctxt, String usageNote) {
|
||||
if (reference == null && target == null)
|
||||
return "null";
|
||||
String res = null;
|
||||
|
@ -4296,7 +4473,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
switch (ctxt) {
|
||||
case ADDITIONAL: return context.formatMessage(I18nConstants.BINDING_ADDITIONAL, res);
|
||||
case ADDITIONAL: return context.formatMessage(Utilities.noString(usageNote) ? I18nConstants.BINDING_ADDITIONAL_D : I18nConstants.BINDING_ADDITIONAL_UC, res, usageNote);
|
||||
case MAXVS: return context.formatMessage(I18nConstants.BINDING_MAX, res);
|
||||
default: return res;
|
||||
}
|
||||
|
@ -5718,6 +5895,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
hint(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesDeeplyConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT_HINT, status, standardsStatus);
|
||||
}
|
||||
}
|
||||
if (noExperimentalContent) {
|
||||
String exp = element.getNamedChildValue("experimental");
|
||||
ok = rule(errors, "2024-09-17", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), !"true".equals(exp), I18nConstants.VALIDATION_NO_EXPERIMENTAL_CONTENT) && ok;
|
||||
}
|
||||
|
||||
if (isHL7Core(element) && !isExample()) {
|
||||
ok = checkPublisherConsistency(valContext, errors, element, stack, contained) && ok;
|
||||
|
@ -5886,20 +6067,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
Element div = text.getNamedChild("div", false);
|
||||
if (lang != null && div != null) {
|
||||
XhtmlNode xhtml = div.getXhtml();
|
||||
String l = xhtml.getAttribute("lang");
|
||||
String xl = xhtml.getAttribute("xml:lang");
|
||||
if (l == null && xl == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING1);
|
||||
} else {
|
||||
if (l == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING2);
|
||||
} else if (!l.equals(lang)) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_DIFFERENT1, lang, l);
|
||||
}
|
||||
if (xl == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING3);
|
||||
} else if (!xl.equals(lang)) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_DIFFERENT2, lang, xl);
|
||||
if (xhtml != null) {
|
||||
String l = xhtml.getAttribute("lang");
|
||||
String xl = xhtml.getAttribute("xml:lang");
|
||||
if (l == null && xl == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING1);
|
||||
} else {
|
||||
if (l == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING2);
|
||||
} else if (!l.equals(lang)) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_DIFFERENT1, lang, l);
|
||||
}
|
||||
if (xl == null) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_MISSING3);
|
||||
} else if (!xl.equals(lang)) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, I18nConstants.LANGUAGE_XHTML_LANG_DIFFERENT2, lang, xl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7434,6 +7617,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
|
||||
public long timeNoTX() {
|
||||
return (timeTracker.getOverall() - timeTracker.getTxTime()) / 1000000;
|
||||
}
|
||||
public String reportTimes() {
|
||||
String s = String.format("Times (ms): overall = %d:4, tx = %d, sd = %d, load = %d, fpe = %d, spec = %d", timeTracker.getOverall() / 1000000, timeTracker.getTxTime() / 1000000, timeTracker.getSdTime() / 1000000, timeTracker.getLoadTime() / 1000000, timeTracker.getFpeTime() / 1000000, timeTracker.getSpecTime() / 1000000);
|
||||
timeTracker.reset();
|
||||
|
@ -7840,5 +8026,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
|
||||
}
|
||||
|
||||
public boolean isNoExperimentalContent() {
|
||||
return noExperimentalContent;
|
||||
}
|
||||
|
||||
public void setNoExperimentalContent(boolean noExperimentalContent) {
|
||||
this.noExperimentalContent = noExperimentalContent;
|
||||
}
|
||||
|
||||
public void resetTimes() {
|
||||
timeTracker.reset();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
List<ElementDefinition> snapshot = sd.getSnapshot().getElement();
|
||||
sd.setSnapshot(null);
|
||||
typeName = sd.getTypeName();
|
||||
boolean experimental = "true".equals(src.getNamedChildValue("experimental", false));
|
||||
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), base != null, I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), "StructureDefinition, so can't check the differential")) {
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasDerivation(), I18nConstants.SD_MUST_HAVE_DERIVATION, sd.getUrl())) {
|
||||
|
@ -129,6 +130,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
ok = rule(errors, "2022-11-02", IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")),
|
||||
I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok;
|
||||
}
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !base.getExperimental() || experimental, I18nConstants.SD_BASE_EXPERIMENTAL, sd.getBaseDefinition());
|
||||
}
|
||||
|
||||
List<Element> differentials = src.getChildrenByName("differential");
|
||||
|
@ -136,10 +138,10 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
boolean logical = "logical".equals(src.getNamedChildValue("kind", false));
|
||||
boolean constraint = "constraint".equals(src.getNamedChildValue("derivation", false));
|
||||
for (Element differential : differentials) {
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base) && ok;
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base, experimental) && ok;
|
||||
}
|
||||
for (Element snapshotE : snapshots) {
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base) && ok;
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base, experimental) && ok;
|
||||
}
|
||||
|
||||
// obligation profile support
|
||||
|
@ -189,6 +191,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
|
||||
ok = false;
|
||||
}
|
||||
|
@ -409,19 +412,19 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, String profileType, StructureDefinition base) {
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, String profileType, StructureDefinition base, boolean experimental) {
|
||||
Map<String, String> invariantMap = new HashMap<>();
|
||||
boolean ok = true;
|
||||
List<Element> elements = elementList.getChildrenByName("element");
|
||||
int cc = 0;
|
||||
for (Element element : elements) {
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, profileType, base) && ok;
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, profileType, base, experimental) && ok;
|
||||
cc++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl, String profileType, StructureDefinition base) {
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl, String profileType, StructureDefinition base, boolean experimental) {
|
||||
boolean ok = true;
|
||||
boolean typeMustSupport = false;
|
||||
String path = element.getNamedChildValue("path", false);
|
||||
|
@ -522,7 +525,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("can-bind") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Binding", typeCodes) && ok;
|
||||
}
|
||||
Element binding = element.getNamedChild("binding", false);
|
||||
ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path) && ok;
|
||||
ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path, experimental, sd) && ok;
|
||||
} else {
|
||||
// this is a good idea but there's plenty of cases where the rule isn't met; maybe one day it's worth investing the time to exclude these cases and bring this rule back
|
||||
// String bt = boundType(typeCodes);
|
||||
|
@ -986,7 +989,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
return null;
|
||||
}
|
||||
|
||||
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path) {
|
||||
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path, boolean experimental, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
if (bindableType(typeCodes) == null) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot, I18nConstants.SD_ED_BIND_NO_BINDABLE, path, typeCodes.toString()) && ok;
|
||||
|
@ -1006,11 +1009,129 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||
if (vs != null) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()) && ok;
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) {
|
||||
ValueSet vsr = (ValueSet) vs;
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasChildren("additional")) {
|
||||
int i = 0;
|
||||
for (Element ab : binding.getChildren("additional")) {
|
||||
ok = validateAdditionalBinding(errors, ab, stack.push(ab, i, null, null), snapshot, path, experimental) && ok;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (binding.hasExtension(ToolingExtensions.EXT_BINDING_ADDITIONAL)) {
|
||||
int i = 0;
|
||||
for (Element ab : binding.getChildren("extension")) {
|
||||
String url = ab.getNamedChildValue("url");
|
||||
if (ToolingExtensions.EXT_BINDING_ADDITIONAL.equals(url)) {
|
||||
ok = validateAdditionalBindingExtension(errors, ab, stack.push(ab, i, null, null), snapshot, path, experimental, profile) && ok;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, boolean snapshot, String path, boolean experimental) {
|
||||
boolean ok = true;
|
||||
|
||||
if (binding.hasChild("valueSet", false)) {
|
||||
Element valueSet = binding.getNamedChild("valueSet", false);
|
||||
String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference", false);
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
||||
Resource vs = context.fetchResource(Resource.class, ref);
|
||||
|
||||
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
|
||||
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||
if (vs != null) {
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) {
|
||||
ValueSet vsr = (ValueSet) vs;
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasChildren("usage")) {
|
||||
for (Element usage : binding.getChildren("usage")) {
|
||||
warning(errors, "2024-09-20", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, "test");
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBindingExtension(List<ValidationMessage> errors, Element binding, NodeStack stack, boolean snapshot, String path, boolean experimental, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
|
||||
if (binding.hasExtension("valueSet")) {
|
||||
Element valueSet = binding.getExtension("valueSet");
|
||||
Element vv = valueSet.getNamedChild("value");
|
||||
String ref = vv.hasPrimitiveValue() ? vv.primitiveValue() : vv.getNamedChildValue("reference", false);
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
||||
Resource vs = context.fetchResource(Resource.class, ref);
|
||||
|
||||
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
|
||||
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||
if (vs != null) {
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) {
|
||||
ValueSet vsr = (ValueSet) vs;
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasExtension("usage")) {
|
||||
int i = 0;
|
||||
for (Element usage : binding.getChildren("extension")) {
|
||||
String url = usage.getNamedChildValue("url");
|
||||
if ("usage".equals(url)) {
|
||||
Element uv = usage.getNamedChild("value");
|
||||
ok = validateAdditionalBindingUsage(errors, uv, stack.push(uv, -1, null, null), path, profile) && ok;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBindingUsage(List<ValidationMessage> errors, Element usage, NodeStack stack, String path, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
Element cc = usage.getNamedChild("code");
|
||||
if (cc != null) {
|
||||
String system = cc.getNamedChildValue("system");
|
||||
String code = cc.getNamedChildValue("code");
|
||||
if (system != null && system.equals(profile.getUrl())) {
|
||||
ElementDefinition ed = profile.getDifferential().getElementByPath(code);
|
||||
if (ed == null) {
|
||||
ed = profile.getSnapshot().getElementByPath(code);
|
||||
}
|
||||
if (ed == null) {
|
||||
ok = false;
|
||||
rule(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT, system, code);
|
||||
} else {
|
||||
if (usage.hasChild("value")) {
|
||||
String t = usage.getNamedChild("value").fhirType();
|
||||
ok = rule(errors, "2024-09-20", IssueType.BUSINESSRULE, stack.getLiteralPath(), "CodeableConcept".equals(t), I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE, t, "CodeableConcept") && ok;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN, system, code);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -362,6 +362,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
if (content.has("security-checks")) {
|
||||
val.setSecurityChecks(content.get("security-checks").getAsBoolean());
|
||||
}
|
||||
if (content.has("no-experimental-content")) {
|
||||
val.setNoExperimentalContent(content.get("no-experimental-content").getAsBoolean());
|
||||
}
|
||||
if (content.has("noHtmlInMarkdown")) {
|
||||
val.setHtmlInMarkdownCheck(HtmlInMarkdownCheck.ERROR);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
[servers]
|
||||
tx-dev.fhir.org.r2 = http://tx-dev.fhir.org/r2
|
||||
local.fhir.org.r2 = http://local.fhir.org/r2
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
[servers]
|
||||
tx-dev.fhir.org.r3 = http://tx-dev.fhir.org/r3
|
||||
local.fhir.org.r3 = http://local.fhir.org/r3
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -521,7 +521,6 @@ v: {
|
|||
"system" : "http://unitsofmeasure.org",
|
||||
"version" : "2.0.1",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -549,7 +548,6 @@ v: {
|
|||
"code" : "image/jpg",
|
||||
"system" : "urn:ietf:bcp:13",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -577,7 +575,6 @@ v: {
|
|||
"code" : "image/jpg",
|
||||
"system" : "urn:ietf:bcp:13",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -605,7 +602,6 @@ v: {
|
|||
"code" : "application/pdf",
|
||||
"system" : "urn:ietf:bcp:13",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -633,7 +629,6 @@ v: {
|
|||
"code" : "application/pdf",
|
||||
"system" : "urn:ietf:bcp:13",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -654,7 +649,6 @@ v: {
|
|||
"code" : "de-CH",
|
||||
"system" : "urn:ietf:bcp:47",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -720,3 +714,29 @@ v: {
|
|||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "urn:iso:std:iso:3166",
|
||||
"code" : "US",
|
||||
"display" : "United States of America"
|
||||
}]
|
||||
}, "url": "http://hl7.org/fhir/ValueSet/jurisdiction", "version": "3.0.2", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"display" : "United States of America",
|
||||
"code" : "US",
|
||||
"system" : "urn:iso:std:iso:3166",
|
||||
"version" : "2018",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[servers]
|
||||
tx-dev.fhir.org.r3 = http://tx-dev.fhir.org/r3
|
||||
local.fhir.org.r3 = http://local.fhir.org/r3
|
||||
|
||||
|
|
|
@ -1108,7 +1108,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1132,7 +1131,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1159,7 +1157,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'Laboratory test finding (finding)' for http://snomed.info/sct#118246004. Valid display is one of 4 choices: 'Laboratory test finding', 'Laboratory test observations', 'Laboratory test result' or 'Laboratory test finding (navigational concept)' (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1203,7 +1200,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'Chemistry' for http://snomed.info/sct#275711006. Valid display is one of 2 choices: 'Serum chemistry test' or 'Serum chemistry test (procedure)' (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1244,7 +1240,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1268,7 +1263,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1292,7 +1286,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1316,7 +1309,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1340,7 +1332,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1364,7 +1355,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1388,7 +1378,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -1413,7 +1402,6 @@ v: {
|
|||
"error" : "Unknown code '823681000000100' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1455,7 +1443,6 @@ v: {
|
|||
"error" : "Unknown code '886921000000105' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1497,7 +1484,6 @@ v: {
|
|||
"error" : "Unknown code '1077881000000105' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1539,7 +1525,6 @@ v: {
|
|||
"error" : "Unknown code '887181000000106' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1581,7 +1566,6 @@ v: {
|
|||
"error" : "Unknown code '887161000000102' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1623,7 +1607,6 @@ v: {
|
|||
"error" : "Unknown code '1052891000000108' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1665,7 +1648,6 @@ v: {
|
|||
"error" : "Unknown code '715851000000102' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1707,7 +1689,6 @@ v: {
|
|||
"error" : "Unknown code '717121000000105' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1749,7 +1730,6 @@ v: {
|
|||
"error" : "Unknown code '933361000000108' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1791,7 +1771,6 @@ v: {
|
|||
"error" : "Unknown code '887171000000109' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1833,7 +1812,6 @@ v: {
|
|||
"error" : "Unknown code '887201000000105' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1875,7 +1853,6 @@ v: {
|
|||
"error" : "Unknown code '1052951000000105' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1917,7 +1894,6 @@ v: {
|
|||
"error" : "Unknown code '886731000000109' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -1959,7 +1935,6 @@ v: {
|
|||
"error" : "Unknown code '887231000000104' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -2001,7 +1976,6 @@ v: {
|
|||
"error" : "Unknown code '9290701000001101' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -2042,7 +2016,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -2066,7 +2039,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -2089,7 +2061,6 @@ v: {
|
|||
"system" : "http://snomed.info/sct",
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -2113,7 +2084,6 @@ v: {
|
|||
"error" : "Unknown code '11181000146103' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/900000000000207008/version/20240201'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -2137,3 +2107,61 @@ v: {
|
|||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "http://snomed.info/sct",
|
||||
"code" : "17621005",
|
||||
"display" : "Normal (qualifier value)"
|
||||
}]
|
||||
}, "url": "http://hl7.org/fhir/ValueSet/security-labels", "version": "3.0.2", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"version" : "http://snomed.info/sct/900000000000207008/version/20240201",
|
||||
"severity" : "error",
|
||||
"error" : "No valid coding was found for the value set 'http://hl7.org/fhir/ValueSet/security-labels|3.0.2'; The provided code 'http://snomed.info/sct#17621005 ('Normal (qualifier value)')' was not found in the value set 'http://hl7.org/fhir/ValueSet/security-labels|3.0.2'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r3",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r3"
|
||||
}],
|
||||
"severity" : "information",
|
||||
"code" : "code-invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "this-code-not-in-vs"
|
||||
}],
|
||||
"text" : "The provided code 'http://snomed.info/sct#17621005 ('Normal (qualifier value)')' was not found in the value set 'http://hl7.org/fhir/ValueSet/security-labels|3.0.2'"
|
||||
},
|
||||
"location" : ["CodeableConcept.coding[0].code"],
|
||||
"expression" : ["CodeableConcept.coding[0].code"]
|
||||
},
|
||||
{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r3"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "code-invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-in-vs"
|
||||
}],
|
||||
"text" : "No valid coding was found for the value set 'http://hl7.org/fhir/ValueSet/security-labels|3.0.2'"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -39,10 +39,68 @@ v: {
|
|||
"system" : "http://www.ada.org/snodent",
|
||||
"version" : "2.1.0",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "http://www.ada.org/snodent",
|
||||
"code" : "210965D",
|
||||
"display" : "Anterior part of lower alveolar ridge"
|
||||
}],
|
||||
"text" : "Anterior part of lower alveolar ridge"
|
||||
}, "url": "http://hl7.org/fhir/us/dental-data-exchange/ValueSet/dental-anatomy", "version": "1.0.0", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"version" : "2.1.0",
|
||||
"severity" : "error",
|
||||
"error" : "No valid coding was found for the value set 'http://hl7.org/fhir/us/dental-data-exchange/ValueSet/dental-anatomy|1.0.0'; The provided code 'http://www.ada.org/snodent#210965D ('Anterior part of lower alveolar ridge')' was not found in the value set 'http://hl7.org/fhir/us/dental-data-exchange/ValueSet/dental-anatomy|1.0.0'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://local.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://local.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "information",
|
||||
"code" : "code-invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "this-code-not-in-vs"
|
||||
}],
|
||||
"text" : "The provided code 'http://www.ada.org/snodent#210965D ('Anterior part of lower alveolar ridge')' was not found in the value set 'http://hl7.org/fhir/us/dental-data-exchange/ValueSet/dental-anatomy|1.0.0'"
|
||||
},
|
||||
"location" : ["CodeableConcept.coding[0].code"],
|
||||
"expression" : ["CodeableConcept.coding[0].code"]
|
||||
},
|
||||
{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://local.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "code-invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-in-vs"
|
||||
}],
|
||||
"text" : "No valid coding was found for the value set 'http://hl7.org/fhir/us/dental-data-exchange/ValueSet/dental-anatomy|1.0.0'"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
|
@ -8422,7 +8422,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'O2 % BldC Oximetry' for http://loinc.org#59408-5. Valid display is 'Oxygen saturation in Arterial blood by Pulse oximetry' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8463,7 +8462,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8489,7 +8487,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#59408-5' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-vitalsignresult--0|4.0.1'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8529,7 +8526,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8553,7 +8549,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8579,7 +8574,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#3150-0' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-vitalsignresult--0|4.0.1'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8623,7 +8617,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'Flow Rate' for http://loinc.org#3151-8. Valid display is 'Inhaled oxygen flow rate' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8666,7 +8659,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#3151-8' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-vitalsignresult--0|4.0.1'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8706,7 +8698,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8732,7 +8723,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#2708-6' was not found in the value set 'http://hl7.org/fhir/us/core/ValueSet/us-core-vital-signs--0|4.0.0'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8772,7 +8762,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8795,7 +8784,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8818,7 +8806,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8844,7 +8831,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#100066-0' was not found in the value set 'http://hl7.org/fhir/test/StructureDefinition/additional-bindings-vs1--0|1.0.0'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -8884,7 +8870,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8907,7 +8892,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8930,7 +8914,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8954,7 +8937,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -8978,7 +8960,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9002,7 +8983,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9026,7 +9006,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9049,7 +9028,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9073,7 +9051,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9096,7 +9073,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9120,7 +9096,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9143,7 +9118,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9167,7 +9141,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9190,7 +9163,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9214,7 +9186,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9237,7 +9208,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9261,7 +9231,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9284,7 +9253,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9308,7 +9276,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9332,7 +9299,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9359,7 +9325,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'Patient Authorization Signature' for http://loinc.org#59284-0. Valid display is 'Consent Document' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -9399,7 +9364,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9423,7 +9387,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9446,7 +9409,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9470,7 +9432,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9494,7 +9455,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9518,7 +9478,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9545,7 +9504,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'NDC labeler code request' for http://loinc.org#51726-8. Valid display is 'FDA product label NDC labeler code request' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -9586,7 +9544,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9611,7 +9568,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9634,7 +9590,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9662,7 +9617,6 @@ v: {
|
|||
"error" : "Wrong Display Name 'Allergies and adverse reactions' for http://loinc.org#48765-2. Valid display is 'Allergies and adverse reactions Document' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -9703,7 +9657,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9726,7 +9679,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9749,7 +9701,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9773,7 +9724,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9796,7 +9746,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9821,7 +9770,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9845,7 +9793,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9868,7 +9815,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9892,7 +9838,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9915,7 +9860,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9939,7 +9883,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9962,7 +9905,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -9986,7 +9928,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10010,7 +9951,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10033,7 +9973,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10057,7 +9996,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10080,7 +10018,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10103,7 +10040,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10128,7 +10064,6 @@ v: {
|
|||
"error" : "Unknown code '<27>g<EFBFBD><67>' in the CodeSystem 'http://loinc.org' version '2.77'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -10169,7 +10104,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10196,7 +10130,6 @@ v: {
|
|||
"error" : "Wrong Display Name '<27><><EFBFBD><EFBFBD>' for http://loinc.org#18684-1. Valid display is 'First Blood pressure Set' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -10240,7 +10173,6 @@ v: {
|
|||
"error" : "Wrong Display Name '<27><><EFBFBD>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' for http://loinc.org#8480-6. Valid display is 'Systolic blood pressure' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -10284,7 +10216,6 @@ v: {
|
|||
"error" : "Wrong Display Name '<27>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' for http://loinc.org#8462-4. Valid display is 'Diastolic blood pressure' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -10325,7 +10256,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10349,7 +10279,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10373,7 +10302,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10397,7 +10325,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10422,7 +10349,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10447,7 +10373,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10471,7 +10396,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10495,7 +10419,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10518,7 +10441,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10541,7 +10463,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10564,7 +10485,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10587,7 +10507,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10610,7 +10529,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10633,7 +10551,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10656,7 +10573,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10679,7 +10595,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10702,7 +10617,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10737,7 +10651,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10772,7 +10685,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10807,7 +10719,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10831,7 +10742,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10854,7 +10764,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10877,7 +10786,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10901,7 +10809,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10927,7 +10834,6 @@ v: {
|
|||
"error" : "The provided code 'http://loinc.org#76534-7' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-vitalsignresult--0|4.0.1'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
|
@ -10967,7 +10873,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -10991,7 +10896,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11015,7 +10919,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11039,7 +10942,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11063,7 +10965,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11087,7 +10988,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11111,7 +11011,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11135,7 +11034,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11158,7 +11056,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11181,7 +11078,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11205,7 +11101,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11229,7 +11124,6 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
@ -11252,6 +11146,82 @@ v: {
|
|||
"system" : "http://loinc.org",
|
||||
"version" : "2.77",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "59408-5",
|
||||
"display" : "O2 % BldC Oximetry"
|
||||
},
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "2708-6",
|
||||
"display" : "Oxygen saturation in Arterial blood"
|
||||
}]
|
||||
}, "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-vital-signs", "version": "4.0.0", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"display" : "Oxygen saturation in Arterial blood",
|
||||
"code" : "2708-6",
|
||||
"system" : "http://loinc.org",
|
||||
"version" : "2.78",
|
||||
"severity" : "error",
|
||||
"error" : "Wrong Display Name 'O2 % BldC Oximetry' for http://loinc.org#59408-5. Valid display is one of 3 choices: 'Oxygen saturation in Arterial blood by Pulse oximetry' (en-US), 'Oxygen saturation in Arterial blood by Pulse oximetry' (en-US) or 'SaO2 % BldA PulseOx' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "invalid-display"
|
||||
}],
|
||||
"text" : "Wrong Display Name 'O2 % BldC Oximetry' for http://loinc.org#59408-5. Valid display is one of 3 choices: 'Oxygen saturation in Arterial blood by Pulse oximetry' (en-US), 'Oxygen saturation in Arterial blood by Pulse oximetry' (en-US) or 'SaO2 % BldA PulseOx' (en-US) (for the language(s) 'en-US')"
|
||||
},
|
||||
"location" : ["CodeableConcept.coding[0].display"],
|
||||
"expression" : ["CodeableConcept.coding[0].display"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "3150-0",
|
||||
"display" : "Inhaled Oxygen Concentration"
|
||||
}]
|
||||
}, "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-vital-signs", "version": "4.0.0", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"display" : "Inhaled oxygen concentration",
|
||||
"code" : "3150-0",
|
||||
"system" : "http://loinc.org",
|
||||
"version" : "2.78",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
|
@ -11259,3 +11229,49 @@ v: {
|
|||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"coding" : [{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "3151-8",
|
||||
"display" : "Flow Rate"
|
||||
}]
|
||||
}, "url": "http://hl7.org/fhir/us/core/ValueSet/us-core-vital-signs", "version": "4.0.0", "langs":"en-US", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"display" : "Inhaled oxygen flow rate",
|
||||
"code" : "3151-8",
|
||||
"system" : "http://loinc.org",
|
||||
"version" : "2.78",
|
||||
"severity" : "error",
|
||||
"error" : "Wrong Display Name 'Flow Rate' for http://loinc.org#3151-8. Valid display is one of 4 choices: 'Inhaled oxygen flow rate' (en-US), 'Inhaled oxygen flow rate' (en-US), 'Inhaled O2 flow rate' (en-US) or 'Inhaled oxygen' (en-US) (for the language(s) 'en-US')",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "invalid-display"
|
||||
}],
|
||||
"text" : "Wrong Display Name 'Flow Rate' for http://loinc.org#3151-8. Valid display is one of 4 choices: 'Inhaled oxygen flow rate' (en-US), 'Inhaled oxygen flow rate' (en-US), 'Inhaled O2 flow rate' (en-US) or 'Inhaled oxygen' (en-US) (for the language(s) 'en-US')"
|
||||
},
|
||||
"location" : ["CodeableConcept.coding[0].display"],
|
||||
"expression" : ["CodeableConcept.coding[0].display"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue