Merge pull request #539 from hapifhir/gg-20210617-cda
* CDA: Fix erroneous type validation on CDA templates
This commit is contained in:
commit
4915f5ccb3
|
@ -4,14 +4,22 @@ Validator:
|
|||
* don't fail with an exception if an unknown resource type appears in contained resource
|
||||
* improved validation for some value sets that are based on unknown code systems
|
||||
* add the -verbose parameter, and add additional verbose messages
|
||||
* CDA: Fix erroneous type validation on CDA templates
|
||||
|
||||
Conversion code:
|
||||
|
||||
* Ignoring abatementBoolean when converting from dstu2 to r4
|
||||
|
||||
Snapshot generator:
|
||||
|
||||
* CDA: Suppress erroneous "Expansion" text appearing in view
|
||||
* CDA: Don't delete binding information in snapshot for CDA bindable data types
|
||||
|
||||
Other code changes:
|
||||
|
||||
* Fix rendering of slices so type on slicer is not hidden
|
||||
* Fix rendering for most resources - remove empty tables (e.g. text element, that shouldn't render)
|
||||
* Fix NPE rendering code systems with some kinds of properties
|
||||
* Improve rendering of questionnaires (icons, option sets)
|
||||
* Rendering: add support for CodeableReference
|
||||
* Rendering: Support binding mode and XML element information
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package org.hl7.fhir.r5.conformance;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
@ -2226,7 +2230,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
private boolean checkExtensionDoco(ElementDefinition base) {
|
||||
// see task 3970. For an extension, there's no point copying across all the underlying definitional stuff
|
||||
boolean isExtension = base.getPath().equals("Extension") || base.getPath().endsWith(".extension") || base.getPath().endsWith(".modifierExtension");
|
||||
boolean isExtension = (base.getPath().equals("Extension") || base.getPath().endsWith(".extension") || base.getPath().endsWith(".modifierExtension")) &&
|
||||
(!base.hasBase() || !"II.extension".equals(base.getBase().getPath()));
|
||||
if (isExtension) {
|
||||
base.setDefinition("An Extension");
|
||||
base.setShort("Extension");
|
||||
|
@ -3086,6 +3091,10 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (Utilities.existsInList(tr.getWorkingCode(), "Coding", "CodeableConcept", "Quantity", "uri", "string", "code")) {
|
||||
return true;
|
||||
}
|
||||
StructureDefinition sd = context.fetchTypeDefinition(tr.getCode());
|
||||
if (sd != null && sd.hasExtension(ToolingExtensions.EXT_BINDING_STYLE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -4496,6 +4505,31 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Slice")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, describeSlice(definition.getSlicing()), null));
|
||||
}
|
||||
if (!definition.getPath().contains(".") && ToolingExtensions.hasExtension(profile, ToolingExtensions.EXT_BINDING_STYLE)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Binding")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, "This type can be bound to a value set using the ", null));
|
||||
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_BINDING_STYLE), null));
|
||||
c.getPieces().add(gen.new Piece(null, " binding style", null));
|
||||
|
||||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAME), null));
|
||||
c.getPieces().add(gen.new Piece(null, " (", null));
|
||||
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
|
||||
c.getPieces().add(gen.new Piece(null, ")", null));
|
||||
} else {
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Element Name")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAME), null));
|
||||
}
|
||||
} else if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
|
||||
}
|
||||
if (definition != null) {
|
||||
ElementDefinitionBindingComponent binding = null;
|
||||
if (valueDefn != null && valueDefn.hasBinding() && !valueDefn.getBinding().isEmpty())
|
||||
|
@ -4742,8 +4776,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
String s = b.primitiveValue();
|
||||
// ok. let's see if we can find a relevant link for this
|
||||
String link = null;
|
||||
if (Utilities.isAbsoluteUrl(s))
|
||||
if (Utilities.isAbsoluteUrl(s)) {
|
||||
link = pkp.getLinkForUrl(corePath, s);
|
||||
}
|
||||
c.getPieces().add(gen.new Piece(link, s, null).addStyle("color: darkgreen"));
|
||||
} else {
|
||||
c = gen.new Cell();
|
||||
|
|
|
@ -1209,7 +1209,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (class_ == Resource.class || class_ == null) {
|
||||
if (structures.has(uri)) {
|
||||
return (T) structures.get(uri, version);
|
||||
}
|
||||
}
|
||||
if (guides.has(uri)) {
|
||||
return (T) guides.get(uri, version);
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
for (String e : pi.dependencies()) {
|
||||
if (!loadedPackages.contains(e) && !VersionUtilities.isCorePackage(e)) {
|
||||
NpmPackage npm = pcm.loadPackage(e);
|
||||
if (!version.equals(npm.fhirVersion())) {
|
||||
if (!VersionUtilities.versionsMatch(version, npm.fhirVersion())) {
|
||||
System.out.println(formatMessage(I18nConstants.PACKAGE_VERSION_MISMATCH, e, version, npm.fhirVersion(), path));
|
||||
}
|
||||
t = t + loadFromPackageAndDependenciesInt(npm, loader.getNewLoader(npm), pcm, path+" -> "+npm.name()+"#"+npm.version());
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
|
|||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.CodeableReference;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ContactPoint;
|
||||
import org.hl7.fhir.r5.model.DataRequirement;
|
||||
|
@ -552,6 +553,15 @@ public class DataRenderer extends Renderer {
|
|||
renderCodeableConcept(x, cc, false);
|
||||
}
|
||||
|
||||
protected void renderCodeableReference(XhtmlNode x, CodeableReference e, boolean showCodeDetails) {
|
||||
if (e.hasConcept()) {
|
||||
renderCodeableConcept(x, e.getConcept(), showCodeDetails);
|
||||
}
|
||||
if (e.hasReference()) {
|
||||
renderReference(x, e.getReference());
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc, boolean showCodeDetails) {
|
||||
if (cc.isEmpty()) {
|
||||
return;
|
||||
|
|
|
@ -306,12 +306,14 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
else if (e instanceof Enumeration) {
|
||||
Object ev = ((Enumeration<?>) e).getValue();
|
||||
x.addText(ev == null ? "" : ev.toString()); // todo: look up a display name if there is one
|
||||
} else if (e instanceof BooleanType)
|
||||
} else if (e instanceof BooleanType) {
|
||||
x.addText(((BooleanType) e).getValue().toString());
|
||||
else if (e instanceof CodeableConcept) {
|
||||
} else if (e instanceof CodeableConcept) {
|
||||
renderCodeableConcept(x, (CodeableConcept) e, showCodeDetails);
|
||||
} else if (e instanceof Coding) {
|
||||
renderCoding(x, (Coding) e, showCodeDetails);
|
||||
} else if (e instanceof CodeableReference) {
|
||||
renderCodeableReference(x, (CodeableReference) e, showCodeDetails);
|
||||
} else if (e instanceof Annotation) {
|
||||
renderAnnotation(x, (Annotation) e);
|
||||
} else if (e instanceof Identifier) {
|
||||
|
|
|
@ -184,6 +184,9 @@ public class ToolingExtensions {
|
|||
public static final String EXT_TRANSLATABLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable";
|
||||
public static final String EXT_PATTERN = "http://hl7.org/fhir/StructureDefinition/elementdefinition-pattern";
|
||||
public static final String EXT_BINDING_METHOD = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-method";
|
||||
public static final String EXT_XML_NAMESPACE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace";
|
||||
public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name";
|
||||
public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-style";
|
||||
|
||||
// specific extension helpers
|
||||
|
||||
|
|
|
@ -452,7 +452,6 @@ public class VersionUtilities {
|
|||
res.add("TerminologyCapabilities");
|
||||
res.add("TestScript");
|
||||
res.add("ValueSet");
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -465,5 +464,11 @@ public class VersionUtilities {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static boolean versionsMatch(String v1, String v2) {
|
||||
String mm1 = getMajMin(v1);
|
||||
String mm2 = getMajMin(v2);
|
||||
return mm1 != null && mm2 != null && mm1.equals(mm2);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -245,9 +245,10 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
|
||||
if (code.equals("Reference")) {
|
||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||
String t = determineBaseType(sd);
|
||||
StructureDefinition t = determineBaseType(sd);
|
||||
if (t == null) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
throw new Error("What to do about this?");
|
||||
} else {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path);
|
||||
}
|
||||
|
@ -257,9 +258,10 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
sd = getXverExt(errors, stack.getLiteralPath(), profile, p);
|
||||
}
|
||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||
String t = determineBaseType(sd);
|
||||
StructureDefinition t = determineBaseType(sd);
|
||||
if (t == null) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
throw new Error("What to do about this?");
|
||||
} else {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path);
|
||||
}
|
||||
|
@ -288,9 +290,9 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
sd = getXverExt(errors, stack.getLiteralPath(), profile, p);
|
||||
}
|
||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||
String t = determineBaseType(sd);
|
||||
StructureDefinition t = determineBaseType(sd);
|
||||
if (t == null) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
} else {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path);
|
||||
}
|
||||
|
@ -302,18 +304,18 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
|
||||
if (code.equals("Reference")) {
|
||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||
String t = determineBaseType(sd);
|
||||
StructureDefinition t = determineBaseType(sd);
|
||||
if (t == null) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
} else {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Resource");
|
||||
}
|
||||
}
|
||||
} else if (code.equals("canonical")) {
|
||||
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
|
||||
String t = determineBaseType(sd);
|
||||
StructureDefinition t = determineBaseType(sd);
|
||||
if (t == null) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
|
||||
} else if (!VersionUtilities.isR5Ver(context.getVersion())) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t) || "Resource".equals(t), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource");
|
||||
} else {
|
||||
|
@ -325,14 +327,16 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isInstanceOf(String t, String code) {
|
||||
StructureDefinition sd = context.fetchTypeDefinition(t);
|
||||
private boolean isInstanceOf(StructureDefinition sd, String code) {
|
||||
while (sd != null) {
|
||||
if (sd.getType().equals(code)) {
|
||||
return true;
|
||||
}
|
||||
if (sd.getUrl().equals(code)) {
|
||||
return true;
|
||||
}
|
||||
sd = sd.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()) : null;
|
||||
if (!(VersionUtilities.isR2Ver(context.getVersion()) || VersionUtilities.isR2BVer(context.getVersion())) && sd != null && !sd.getAbstract()) {
|
||||
if (!(VersionUtilities.isR2Ver(context.getVersion()) || VersionUtilities.isR2BVer(context.getVersion())) && sd != null && !sd.getAbstract() && sd.getKind() != StructureDefinitionKind.LOGICAL) {
|
||||
sd = null;
|
||||
}
|
||||
}
|
||||
|
@ -340,11 +344,11 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
return false;
|
||||
}
|
||||
|
||||
private String determineBaseType(StructureDefinition sd) {
|
||||
private StructureDefinition determineBaseType(StructureDefinition sd) {
|
||||
while (sd != null && !sd.hasType() && sd.getDerivation() == TypeDerivationRule.CONSTRAINT) {
|
||||
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
}
|
||||
return sd == null ? null : sd.getType();
|
||||
return sd;
|
||||
}
|
||||
|
||||
private boolean hasMustSupportExtension(Element type) {
|
||||
|
|
Loading…
Reference in New Issue