Merge pull request #1753 from hapifhir/2024-09-gg-connectathon

2024 09 gg connectathon
This commit is contained in:
Grahame Grieve 2024-09-22 07:57:18 -04:00 committed by GitHub
commit 09ad0005b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 779 additions and 282 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -1471,15 +1471,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) {

View File

@ -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;
}
}
@ -175,7 +175,11 @@ public class AdditionalBindingsRenderer {
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;
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();
}

View File

@ -1302,6 +1302,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,11 +1315,14 @@ 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) {
String s = context.getTranslated(cc.child("Text"));
@ -1860,8 +1867,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"));
}

View File

@ -42,12 +42,14 @@ public class TerminologyOperationContext {
private IWorkerContext worker;
private boolean original;
private ValidationOptions options;
private String name;
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;
if (EXPANSION_DEAD_TIME_SECS == 0 || debugging) {
deadTime = 0;
@ -56,13 +58,14 @@ public class TerminologyOperationContext {
}
}
private TerminologyOperationContext(ValidationOptions options) {
private TerminologyOperationContext(ValidationOptions options, String name) {
super();
this.options = options;
this.name = name;
}
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;
@ -71,7 +74,7 @@ public class TerminologyOperationContext {
public void deadCheck() {
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);
throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS, name), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY);
}
}

View File

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

View File

@ -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";
@ -1111,4 +1113,7 @@ public class I18nConstants {
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";
}

View File

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

View File

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

View File

@ -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}
@ -1143,3 +1145,6 @@ NO_VALID_DISPLAY_AT_ALL = Cannot validate display Name ''{0}'' for {1}#{2}: No d
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}

View File

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

View File

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

View File

@ -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
@ -1356,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) {
@ -1394,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;
@ -1424,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))) {
@ -1436,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 {
@ -1493,15 +1656,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// we've already handled the warnings / errors about this, and set the status correctly. We don't need to do anything more?
} else {
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));
}
}
}
@ -1648,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")) {
@ -1660,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());
}
}
}
@ -1698,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;
}
}
}
@ -1728,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))) {
@ -1754,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){
@ -1896,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();
@ -1936,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();
@ -1966,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) {
@ -2029,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);
@ -2038,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) {
@ -2068,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))) {
@ -2098,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) {
@ -3017,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;
}
@ -3466,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) {
@ -3479,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;
@ -3563,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){
@ -4279,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;
@ -4297,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;
}
@ -5891,6 +6067,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
Element div = text.getNamedChild("div", false);
if (lang != null && div != null) {
XhtmlNode xhtml = div.getXhtml();
if (xhtml != null) {
String l = xhtml.getAttribute("lang");
String xl = xhtml.getAttribute("xml:lang");
if (l == null && xl == null) {
@ -5909,6 +6086,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
}
}
// security tags are a set (system|code)
Element meta = element.getNamedChild(META, false);
if (meta != null) {
@ -7439,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();
@ -7853,5 +8034,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.noExperimentalContent = noExperimentalContent;
}
public void resetTimes() {
timeTracker.reset();
}
}

View File

@ -191,7 +191,7 @@ public class StructureDefinitionValidator extends BaseValidator {
}
}
} catch (Exception e) {
e.printStackTrace();
//e.printStackTrace();
rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
ok = false;
}
@ -525,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, experimental) && 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);
@ -989,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, boolean experimental) {
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;
@ -1019,6 +1019,119 @@ public class StructureDefinitionValidator extends BaseValidator {
}
}
}
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;
}

View File

@ -0,0 +1,42 @@
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
"code" : "digital-access"
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "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: {
"code" : "digital-access",
"system" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
"severity" : "error",
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs' could not be found, so the code cannot be validated",
"class" : "CODESYSTEM_UNSUPPORTED",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
"issues" : {
"resourceType" : "OperationOutcome",
"issue" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
"valueUrl" : "http://tx-dev.fhir.org/r4"
}],
"severity" : "error",
"code" : "not-found",
"details" : {
"coding" : [{
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
"code" : "not-found"
}],
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs' could not be found, so the code cannot be validated"
},
"location" : ["Coding.system"],
"expression" : ["Coding.system"]
}]
}
}
-------------------------------------------------------------------------------------

View File

@ -0,0 +1,83 @@
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"code" : "digital-access-x"
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "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: {
"code" : "digital-access-x",
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"severity" : "error",
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated",
"class" : "CODESYSTEM_UNSUPPORTED",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"issues" : {
"resourceType" : "OperationOutcome",
"issue" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
"valueUrl" : "http://tx-dev.fhir.org/r4"
}],
"severity" : "error",
"code" : "not-found",
"details" : {
"coding" : [{
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
"code" : "not-found"
}],
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated"
},
"location" : ["Coding.system"],
"expression" : ["Coding.system"]
}]
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"code" : "digital-access"
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "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: {
"code" : "digital-access",
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"severity" : "error",
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated",
"class" : "CODESYSTEM_UNSUPPORTED",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
"issues" : {
"resourceType" : "OperationOutcome",
"issue" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
"valueUrl" : "http://tx-dev.fhir.org/r4"
}],
"severity" : "error",
"code" : "not-found",
"details" : {
"coding" : [{
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
"code" : "not-found"
}],
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated"
},
"location" : ["Coding.system"],
"expression" : ["Coding.system"]
}]
}
}
-------------------------------------------------------------------------------------

View File

@ -82,3 +82,45 @@ v: {
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
"code" : "no-allergy-info",
"display" : "No information about allergies"
}, "valueSet" :null, "langs":"en-NZ", "useServer":"true", "useClient":"false", "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: {
"code" : "no-allergy-info",
"system" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
"severity" : "error",
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips' could not be found, so the code cannot be validated",
"class" : "CODESYSTEM_UNSUPPORTED",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
"issues" : {
"resourceType" : "OperationOutcome",
"issue" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
"valueUrl" : "http://tx-dev.fhir.org/r4"
}],
"severity" : "error",
"code" : "not-found",
"details" : {
"coding" : [{
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
"code" : "not-found"
}],
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips' could not be found, so the code cannot be validated"
},
"location" : ["Coding.system"],
"expression" : ["Coding.system"]
}]
}
}
-------------------------------------------------------------------------------------