Merge remote-tracking branch 'origin/master' into do-20240716-fix-code-validation-for-locale

This commit is contained in:
dotasek 2024-08-05 10:32:51 -04:00
commit eba6868afe
48 changed files with 264 additions and 94 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -506,7 +506,7 @@ public class ProfileUtilities {
for (ElementDefinition e : list) {
if (id.equals(e.getId()))
return getChildMap(profile, e);
return getChildMap(src, e);
}
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_NAME_REFERENCE__AT_PATH_, element.getContentReference(), element.getPath()));

View File

@ -1810,10 +1810,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
cache = checkAddToParams(tc, pin, cs) || cache;
}
for (CodeSystem supp : fetchResourcesByType(CodeSystem.class)) {
if (supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem())) {
for (CodeSystem supp : codeSystems.getSupplements(cs)) {
//if (supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem())) {
assert supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem());
cache = checkAddToParams(tc, pin, supp) || cache;
}
//}
}
return cache;
}
@ -1885,8 +1886,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} else if (p.getName().equals("status")) {
status = ((PrimitiveType<?>) p.getValue()).asStringValue();
} else if (p.getName().equals("x-caused-by-unknown-system")) {
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
unknownSystems.add(((PrimitiveType<?>) p.getValue()).asStringValue());
String unkSystem = ((PrimitiveType<?>) p.getValue()).asStringValue();
if (unkSystem != null && unkSystem.contains("|")) {
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED_VERSION;
system = unkSystem.substring(0, unkSystem.indexOf("|"));
version = unkSystem.substring(unkSystem.indexOf("|")+1);
} else {
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
unknownSystems.add(unkSystem);
}
} else if (p.getName().equals("x-unknown-system")) {
unknownSystems.add(((PrimitiveType<?>) p.getValue()).asStringValue());
} else if (p.getName().equals("warning-withdrawn")) {
@ -1948,6 +1956,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
res.setDefinition(new ConceptDefinitionComponent().setDisplay(display).setCode(code));
res.setDisplay(display);
}
if (system != null) {
res.setSystem(system);
}
if (version != null) {
res.setVersion(version);
}
} else if (message != null && !message.equals("No Message returned")) {
res = new ValidationResult(IssueSeverity.WARNING, message, system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display, null).setTxLink(txLog.getLastId());
} else if (display != null) {

View File

@ -630,6 +630,9 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
public List<T> getSupplements(T cr) {
if (cr == null) {
return new ArrayList<T>();
}
if (cr.hasSourcePackage()) {
List<String> pvl = new ArrayList<>();
pvl.add(cr.getSourcePackage().getVID());

View File

@ -347,10 +347,11 @@ public class Element extends Base implements NamedItem {
if (children == null)
children = new NamedItemList<Element>();
for (Element child : children) {
if (name.equals(child.getName())) {
if (nameMatches(child.getName(), name)) {
if (!child.isPrimitive())
throw new Error("Cannot set a value of a non-primitive type ("+name+" on "+this.getName()+")");
child.setValue(value.primitiveValue());
return;
}
}
@ -1364,14 +1365,18 @@ public class Element extends Base implements NamedItem {
public Element addElement(String name) {
if (children == null)
children = new NamedItemList<Element>();
int insertionPoint = 0;
for (Property p : property.getChildProperties(this.name, type)) {
while (insertionPoint < children.size() && nameMatches(children.get(insertionPoint).getName(), p.getName())) {
insertionPoint++;
}
if (p.getName().equals(name)) {
if (!p.isList() && hasChild(name, false)) {
throw new Error(name+" on "+this.name+" is not a list, so can't add an element");
}
Element ne = new Element(name, p).setFormat(format);
children.add(ne);
children.add(insertionPoint, ne);
return ne;
}
// polymorphic support
@ -1386,7 +1391,7 @@ public class Element extends Base implements NamedItem {
if (p.canBeType(type)) {
Element ne = new Element(name, p).setFormat(format);
ne.setType(type);
children.add(ne);
children.add(insertionPoint, ne);
return ne;
}
}
@ -1396,6 +1401,15 @@ public class Element extends Base implements NamedItem {
throw new Error("Unrecognised property '"+name+"' on "+this.name);
}
private boolean nameMatches(String elementName, String propertyName) {
if (propertyName.endsWith("[x]")) {
String base = propertyName.replace("[x]", "");
return elementName.startsWith(base);
} else {
return elementName.equals(propertyName);
}
}
@Override
public Base copy() {
Element element = new Element(this);

View File

@ -419,8 +419,9 @@ public class Property {
break;
}
}
if (url==null)
if (url==null) {
throw new FHIRException("Unable to find type " + t + " for element " + elementName + " with path " + ed.getPath());
}
sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null)
throw new DefinitionException("Unable to find type '"+t+"' for name '"+elementName+"' on property "+definition.getPath());

View File

@ -4659,7 +4659,7 @@ public class FHIRPathEngine {
}
for (String an : node.getAttributes().keySet()) {
boolean ok = an.startsWith("xmlns") || Utilities.existsInList(an,
"title", "style", "class", "id", "idref", "lang", "xml:lang", "dir", "accesskey", "tabindex",
"title", "style", "class", "id", "idref", "lang", "xml:lang", "xml:space", "dir", "accesskey", "tabindex",
// tables
"span", "width", "align", "valign", "char", "charoff", "abbr", "axis", "headers", "scope", "rowspan", "colspan") ||

View File

@ -157,7 +157,7 @@ public class Base64BinaryType extends PrimitiveType<byte[]> implements IPrimitiv
*/
public void checkValidBase64(String toCheck) throws DataFormatException {
if (!org.hl7.fhir.utilities.Base64.isBase64(toCheck.getBytes())) {
throw new DataFormatException("");
throw new DataFormatException("Invalid Base64 content: "+toCheck.substring(0, 10)+"...");
}
}
}

View File

@ -182,6 +182,8 @@ public class BundleRenderer extends ResourceRenderer {
} else {
RendererFactory.factory(subject, context).buildNarrative(status, sec, subject);
}
} else {
sec.para().b().tx("Unable to resolve subject '"+displayReference(comp.child("subject"))+"'");
}
x.hr();
sec = docSection(x, "Document Content");
@ -212,7 +214,8 @@ public class BundleRenderer extends ResourceRenderer {
}
if (section.has("text")) {
ResourceWrapper narrative = section.child("text");
x.addChildren(narrative.getXhtml());
ResourceWrapper xh = narrative.child("div");
x.addChildren(xh.getXhtml());
}
if (section.has("section")) {
List<ResourceWrapper> sections = section.children("section");

View File

@ -53,7 +53,8 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
renderResourceTechDetails(r, x);
render(status, x, (CapabilityStatement) r.getBase(), r);
} else {
throw new Error("CapabilityStatementRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("CapabilityStatementRenderer only renders native resources directly");
}
}
@ -422,7 +423,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private void addSupportedCSs(RenderingStatus status, XhtmlNode x, CapabilityStatement cap, ResourceWrapper res) throws UnsupportedEncodingException, IOException {
if (cap.hasInstantiates()) {
XhtmlNode p = x.para();
p.tx(cap.getInstantiates().size() > 1 ? "This CapabilityStatement instantiates these CapabilityStatements" : "This CapabilityStatement instantiates the CapabilityStatement");
p.tx(cap.getInstantiates().size() > 1 ? "This CapabilityStatement instantiates these CapabilityStatements " : "This CapabilityStatement instantiates the CapabilityStatement ");
boolean first = true;
for (CanonicalType ct : cap.getInstantiates()) {
if (first) {first = false;} else {p.tx(", ");};
@ -431,7 +432,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
if (cap.hasImports()) {
XhtmlNode p = x.para();
p.tx(cap.getImports().size() > 1 ? "This CapabilityStatement imports these CapabilityStatements" : "This CapabilityStatement imports the CapabilityStatement");
p.tx(cap.getImports().size() > 1 ? "This CapabilityStatement imports these CapabilityStatements " : "This CapabilityStatement imports the CapabilityStatement ");
boolean first = true;
for (CanonicalType ct : cap.getImports()) {
if (first) {first = false;} else {p.tx(", ");};

View File

@ -53,7 +53,8 @@ public class CodeSystemRenderer extends TerminologyRenderer {
genSummaryTable(status, x, (CodeSystem) r.getBase());
render(status, x, (CodeSystem) r.getBase(), r);
} else {
throw new Error("CodeSystemRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("CodeSystemRenderer only renders native resources directly");
}
}

View File

@ -29,7 +29,8 @@ public class CompartmentDefinitionRenderer extends ResourceRenderer {
genSummaryTable(status, x, (CompartmentDefinition) r.getBase());
render(status, x, (CompartmentDefinition) r.getBase());
} else {
throw new Error("CompartmentDefinitionRenderer only renders native resources directly");
// it seems very inlikely this will change
x.para().tx("CompartmentDefinitionRenderer only renders native resources directly");
}
}

View File

@ -49,7 +49,8 @@ public class ConceptMapRenderer extends TerminologyRenderer {
genSummaryTable(status, x, (ConceptMap) r.getBase());
render(status, r, x, (ConceptMap) r.getBase(), false);
} else {
throw new Error("ConceptMapRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("ConceptMapRenderer only renders native resources directly");
}
}

View File

@ -1841,7 +1841,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
else
x.tx("?");
if (q.has("low") && q.child("low").has("unit"))
x.tx(" "+q.child("low").child("unit"));
x.tx(" "+q.child("low").primitiveValue("unit"));
}
public String displayPeriod(ResourceWrapper p) {

View File

@ -149,13 +149,13 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
if (r == null)
container.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_UNABLE));
else if (r.getResource().fhirType().equals("Patient"))
generatePatientSummary(container, r.getResource());
generatePatientSummary(status, container, r.getResource());
else
container.tx(context.formatPhrase(RenderingContext.GENERAL_TODO));
}
private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
new PatientRenderer(context).describe(c, r);
private void generatePatientSummary(RenderingStatus status, XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
new PatientRenderer(context).buildSummary(status, c, r);
}
private List<ObservationNode> fetchObservations(List<ResourceWrapper> list) throws UnsupportedEncodingException, FHIRException, IOException {

View File

@ -50,7 +50,8 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
genSummaryTable(status, x, (ExampleScenario) r.getBase());
render(status, x, (ExampleScenario) r.getBase(), r);
} else {
throw new Error("ExampleScenarioRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("ExampleScenarioRenderer only renders native resources directly");
}
}

View File

@ -25,7 +25,8 @@ public class ImplementationGuideRenderer extends ResourceRenderer {
genSummaryTable(status, x, (ImplementationGuide) r.getBase());
render(status, x, (ImplementationGuide) r.getBase());
} else {
throw new Error("ImplementationGuideRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("ImplementationGuideRenderer only renders native resources directly");
}
}

View File

@ -29,7 +29,8 @@ public class NamingSystemRenderer extends ResourceRenderer {
genSummaryTable(status, x, (NamingSystem) r.getBase());
render(status, x, (NamingSystem) r.getBase());
} else {
throw new Error("NamingSystemRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("NamingSystemRenderer only renders native resources directly");
}
}

View File

@ -40,7 +40,8 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
genSummaryTable(status, x, (OperationDefinition) r.getBase());
render(status, x, (OperationDefinition) r.getBase());
} else {
throw new Error("OperationDefinitionRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("OperationDefinitionRenderer only renders native resources directly");
}
}

View File

@ -126,14 +126,13 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
private void renderOptions(List<ResourceWrapper> items, XhtmlNode x) {
for (ResourceWrapper i : items) {
renderItemOptions(x, i);
renderItemOptionsList(x, i);
renderOptions(i.children("item"), x);
}
}
public void renderItemOptions(XhtmlNode x, ResourceWrapper i) {
if (i.has("answerOption")) {
assert x.getName().equals("select");
for (ResourceWrapper opt : i.children("answerOption")) {
String value = "??";
String text = "??";
@ -157,6 +156,35 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
x.option(value, text, selected);
}
}
}
public void renderItemOptionsList(XhtmlNode x, ResourceWrapper i) {
if (i.has("answerOption")) {
x.an(context.prefixAnchor("opt-item."+i.primitiveValue("linkId")));
x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_ANSW, i.primitiveValue("linkId"))+" ");
XhtmlNode ul = x.ul();
for (ResourceWrapper opt : i.children("answerOption")) {
XhtmlNode li = ul.li();
li.style("font-size: 11px");
ResourceWrapper v = opt.child("value");
if (v.isPrimitive()) {
li.tx(v.primitiveValue());
} else if (v.fhirType().equals("Coding")) {
String link = v.has("system") ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), v.primitiveValue("system")) : null;
if (link == null) {
li.tx(v.primitiveValue("system")+"#"+v.primitiveValue("code"));
} else {
li.ah(link).tx(displaySystem(v.primitiveValue("system")));
li.tx(": "+v.primitiveValue("code"));
}
if (v.has("display")) {
li.tx(" (\""+v.primitiveValue("display")+"\")");
}
} else {
li.tx("??");
}
}
}
}
private boolean hasAnyOptions(List<ResourceWrapper> items) {

View File

@ -150,6 +150,9 @@ public abstract class ResourceRenderer extends DataRenderer {
public abstract void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome;
public abstract String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException;
public void buildSummary(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws UnsupportedEncodingException, IOException {
x.tx(buildSummary(r));
}
public String canonicalTitle(ResourceWrapper r) {
if (r.has("title")) {
@ -870,7 +873,7 @@ public abstract class ResourceRenderer extends DataRenderer {
boolean sfirst = true;
p = plateStyle(div.para());
if (versionId != null) {
p.tx(context.formatPhrase(RenderingContext.RES_REND_VER, versionId));
p.tx(context.formatPhrase(RenderingContext.RES_REND_VER, versionId.primitiveValue()));
sfirst = false;
}
if (lastUpdated != null) {

View File

@ -41,7 +41,8 @@ public class SearchParameterRenderer extends TerminologyRenderer {
render(status, x, (SearchParameter) r.getBase());
} else {
throw new Error("SearchParameterRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("SearchParameterRenderer only renders native resources directly");
}
}

View File

@ -103,18 +103,20 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
@Override
public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
if (!r.isDirect()) {
throw new Error("StructureDefinitionRenderer only renders native resources directly");
}
renderResourceTechDetails(r, x);
StructureDefinition sd = (StructureDefinition) r.getBase();
genSummaryTable(status, x, sd);
if (context.getStructureMode() == StructureDefinitionRendererMode.DATA_DICT) {
renderDict(status, sd, sd.getDifferential().getElement(), x.table("dict"), false, GEN_MODE_DIFF, "", r);
} else {
x.addChildNode(generateTable(status, context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false,
context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context.withUniqueLocalPrefix(null), "r", r));
}
status.setExtensions(true);
// it seems very unlikely that this will change in the future
x.para().tx("StructureDefinitionRenderer only renders native resources directly");
} else {
renderResourceTechDetails(r, x);
StructureDefinition sd = (StructureDefinition) r.getBase();
genSummaryTable(status, x, sd);
if (context.getStructureMode() == StructureDefinitionRendererMode.DATA_DICT) {
renderDict(status, sd, sd.getDifferential().getElement(), x.table("dict"), false, GEN_MODE_DIFF, "", r);
} else {
x.addChildNode(generateTable(status, context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false,
context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context.withUniqueLocalPrefix(null), "r", r));
}
status.setExtensions(true);
}
}
@Override

View File

@ -57,7 +57,8 @@ public class StructureMapRenderer extends TerminologyRenderer {
genSummaryTable(status, x, (StructureMap) r.getBase());
renderMap(status, x.pre("fml"), (StructureMap) r.getBase());
} else {
throw new Error("StructureMapRenderer only renders native resources directly");
// the intention is to change this in the future
x.para().tx("StructureMapRenderer only renders native resources directly");
}
}

View File

@ -73,21 +73,23 @@ public class ValueSetRenderer extends TerminologyRenderer {
@Override
public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
if (!r.isDirect()) {
throw new Error("ValueSetRenderer only renders native resources directly");
}
renderResourceTechDetails(r, x);
ValueSet vs = (ValueSet) r.getBase();
genSummaryTable(status, x, vs);
List<UsedConceptMap> maps = findReleventMaps(vs);
if (vs.hasExpansion()) {
// for now, we just accept an expansion if there is one
generateExpansion(status, r, x, vs, false, maps);
// the intention is to change this in the future
x.para().tx("ValueSetRenderer only renders native resources directly");
} else {
generateComposition(status, r, x, vs, false, maps);
renderResourceTechDetails(r, x);
ValueSet vs = (ValueSet) r.getBase();
genSummaryTable(status, x, vs);
List<UsedConceptMap> maps = findReleventMaps(vs);
if (vs.hasExpansion()) {
// for now, we just accept an expansion if there is one
generateExpansion(status, r, x, vs, false, maps);
} else {
generateComposition(status, r, x, vs, false, maps);
}
}
}
@Override
public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {

View File

@ -1,7 +1,7 @@
package org.hl7.fhir.r5.terminologies.utilities;
public enum TerminologyServiceErrorClass {
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY, PROCESSING;
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, CODESYSTEM_UNSUPPORTED_VERSION, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY, PROCESSING;
public boolean isInfrastructure() {
return this == NOSERVICE || this == SERVER_ERROR || this == VALUESET_UNSUPPORTED;

View File

@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.ContactDetail;
import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.utilities.HL7WorkGroups;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.xml.XMLUtil;
@ -71,16 +72,18 @@ public class CanonicalResourceUtilities {
if (ext == null) {
ext = res.addElement("extension");
ext.setChildValue("url", ToolingExtensions.EXT_WORKGROUP);
}
ext.setChildValue("value[x]", new CodeType(code));
if (!Utilities.existsInList(res.fhirType(), "ClinicalUseDefinition")) {
res.setChildValue("publisher", "HL7 International / "+wg.getName());
while (res.hasChildren("contact")) {
res.removeChild("contact");
}
Element c = res.addElement("contact");
Element t = c.addElement("telecom");
t.setChildValue("system", "url");
t.setChildValue("value", wg.getLink());
}
ext.setChildValue("valueCode", new CodeType(code));
res.setChildValue("publisher", "HL7 International / "+wg.getName());
while (res.hasChildren("contact")) {
res.removeChild("contact");
}
Element c = res.addElement("contact");
Element t = c.addElement("telecom");
t.setChildValue("system", "url");
t.setChildValue("value", wg.getLink());
}
}
//

View File

@ -233,7 +233,7 @@ public class NarrativeGenerationTests {
@ParameterizedTest(name = "{index}: file {0}")
@MethodSource("data")
public void test(String id, TestDetails test) throws Exception {
XhtmlNode.setCheckPara(true);
XhtmlNode.setCheckParaGeneral(true);
if (test.getRegister() != null) {
if (test.getRegister().endsWith(".json")) {
context.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getRegister())));

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -157,6 +157,7 @@ public class I18nConstants {
public static final String CONCEPTMAP_SHAREABLE_MISSING = "CONCEPTMAP_SHAREABLE_MISSING";
public static final String CONCEPTMAP_SHAREABLE_MISSING_HL7 = "CONCEPTMAP_SHAREABLE_MISSING_HL7";
public static final String CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM = "CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM";
public static final String CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM_VERSION = "CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM_VERSION";
public static final String CONCEPTMAP_VS_INVALID_CONCEPT_CODE = "CONCEPTMAP_VS_INVALID_CONCEPT_CODE";
public static final String CONCEPTMAP_VS_INVALID_CONCEPT_CODE_VER = "CONCEPTMAP_VS_INVALID_CONCEPT_CODE_VER";
public static final String CONCEPTMAP_VS_TOO_MANY_CODES = "CONCEPTMAP_VS_TOO_MANY_CODES";
@ -1102,4 +1103,6 @@ public class I18nConstants {
public static final String TYPE_SPECIFIC_CHECKS_DT_XHTML_ACTIVE_HREF = "TYPE_SPECIFIC_CHECKS_DT_XHTML_ACTIVE_HREF";
public static final String TYPE_SPECIFIC_CHECKS_DT_XHTML_UNKNOWN_HREF = "TYPE_SPECIFIC_CHECKS_DT_XHTML_UNKNOWN_HREF";
public static final String TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF = "TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF";
public static final String SM_TARGET_TYPE_UNKNOWN = "SM_TARGET_TYPE_UNKNOWN";
public static final String XHTML_XHTML_ATTRIBUTE_XML_SPACE = "XHTML_XHTML_ATTRIBUTE_XML_SPACE";
}

View File

@ -72,7 +72,9 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
}
}
private static boolean checkPara = false;
private static boolean checkParaGeneral = false;
private boolean checkParaTree = false;
public static final String NBSP = Character.toString((char)0xa0);
public static final String XMLNS = "http://www.w3.org/1999/xhtml";
private static final String DECL_XMLNS = " xmlns=\""+XMLNS+"\"";
@ -91,6 +93,7 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
public XhtmlNode() {
super();
checkParaTree = checkParaGeneral;
}
@ -119,7 +122,7 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
public XhtmlNode setName(String name) {
assert name.contains(":") == false : "Name should not contain any : but was " + name;
if (checkPara && "p".equals(name)) {
if (checkParaTree && "p".equals(name)) {
isInPara = true;
}
this.name = name;
@ -1160,7 +1163,8 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
private void checkWhenAddingNode(XhtmlNode node) {
if (checkPara) {
node.checkParaTree = checkParaTree;
if (checkParaTree) {
if (isInPara) {
if (Utilities.existsInList(node.name, "div", "blockquote", "table", "ol", "ul", "p")) {
throw new Error("Error: attempt to add "+node.name+" inside an html paragraph");
@ -1176,13 +1180,23 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
}
public static boolean isCheckPara() {
return checkPara;
public static boolean isCheckParaGeneral() {
return checkParaGeneral;
}
public static void setCheckPara(boolean checkPara) {
XhtmlNode.checkPara = checkPara;
public static void setCheckParaGeneral(boolean checkParaGeneral) {
XhtmlNode.checkParaGeneral = checkParaGeneral;
}
public boolean isCheckParaTree() {
return checkParaTree;
}
public void setCheckParaTree(boolean checkParaTree) {
this.checkParaTree = checkParaTree;
}
}

View File

@ -500,6 +500,7 @@ public class XhtmlParser {
if ((entryName != null) && !n.getName().equals(entryName))
throw new FHIRFormatError("Unable to Parse HTML - starts with '"+n+"' not '"+entryName+"'"+descLoc());
XhtmlNode root = result.addTag(n.getName());
root.setCheckParaTree(false);
root.setLocation(markLocation());
parseAttributes(root);
markLocation();

View File

@ -545,6 +545,14 @@ public class XMLUtil {
return res;
}
public static Element addChild(Document doc, Element element, String name, String namespace, int indent) {
Node node = doc.createTextNode("\n"+Utilities.padLeft("", ' ', indent));
Element child = doc.createElementNS(namespace, name);
element.appendChild(child);
element.appendChild(node);
return child;
}
public static Element insertChild(Document doc, Element element, String name, String namespace, int indent) {
Node node = doc.createTextNode("\n"+Utilities.padLeft("", ' ', indent));
Element child = doc.createElementNS(namespace, name);

View File

@ -1107,6 +1107,7 @@ xml_attr_value_invalid = The XML Attribute {0} has an invalid character
xml_encoding_invalid = The XML encoding is invalid (must be UTF-8)
Bundle_BUNDLE_Entry_NotFound = Can''t find ''{0}'' in the bundle ({1})
CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM = The code ''{1}'' comes from the system {0} which could not be found, so it''s not known whether it''s valid in the value set ''{2}''
CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM_VERSION = The code ''{1}'' comes from the system {0} version {3} which could not be found, so it''s not known whether it''s valid in the value set ''{2}''
SD_TYPE_PARAMETER_MISSING = The type definition ''{2}'' does not declare a type parameter, but it is derived from the type definition ''{0}'' which has the type parameter ''{1}''
SD_TYPE_PARAMETER_UNKNOWN = The type definition ''{0}'' has the type parameter ''{1}'' but it is not a known type so derivation consistency cannot be checked
SD_TYPE_PARAMETER_INVALID = The type definition ''{2}'' has a type parameter ''{3}'', which is not consistent with it''s ancestor type definition ''{0}'' which has the type parameter ''{1}''
@ -1130,3 +1131,6 @@ TYPE_SPECIFIC_CHECKS_DT_XHTML_EMPTY_HREF = Hyperlink at ''{0}'' for ''{1}'' is e
TYPE_SPECIFIC_CHECKS_DT_XHTML_ACTIVE_HREF = Hyperlink scheme ''{3}'' in ''{0}'' at ''{1}'' for ''{2}'' has active content, which is a security risk and not allowed
TYPE_SPECIFIC_CHECKS_DT_XHTML_UNKNOWN_HREF = Hyperlink scheme ''{3}'' in ''{0}'' at ''{1}'' for ''{2}'' is not a widely supported protocol and should be checked
TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF = Hyperlink scheme ''{3}'' in ''{0}'' at ''{1}'' for ''{2}'' is not a valid hyperlinkable scheme
SM_TARGET_TYPE_UNKNOWN = The type of the target variable is not known: {0}
XHTML_XHTML_ATTRIBUTE_XML_SPACE = The attribute 'xml:space' is legal in XHTML 1.0, and therefore in resources, but was removed in XHTML 1.1, and for this reason it''s use is strongly discouraged

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -3287,7 +3287,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (String an : node.getAttributes().keySet()) {
boolean bok = an.startsWith("xmlns") || HTML_ATTRIBUTES.contains(an) || HTML_COMBO_LIST.contains(node.getName() + "." + an);
if (!bok) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.XHTML_XHTML_ATTRIBUTE_ILLEGAL, an, node.getName()) && ok;
if ("xml:space".equals(an)) {
warning(errors, "2024-08-03", IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.XHTML_XHTML_ATTRIBUTE_XML_SPACE, an, node.getName());
} else {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.XHTML_XHTML_ATTRIBUTE_ILLEGAL, an, node.getName()) && ok;
}
}
}
@ -3314,7 +3318,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (count > 1) {
warning(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_MULTIPLE_MATCHES, href, xpath, node.allText(), CommaSeparatedStringBuilder.join(", ", refs));
}
} else if (href.contains(":")) {
} else if (href.contains(":") && Utilities.isAbsoluteUrl(href)) {
String scheme = href.substring(0, href.indexOf(":"));
if (rule(errors, "2024-07-20", IssueType.INVALID, e.line(), e.col(), path, !isActiveScheme(scheme), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_ACTIVE_HREF, href, xpath, Utilities.stripEoln(node.allText()).trim(), scheme)) {
if (rule(errors, "2024-07-20", IssueType.INVALID, e.line(), e.col(), path, isLiteralScheme(scheme), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF, href, xpath, Utilities.stripEoln(node.allText()).trim(), scheme)) {

View File

@ -171,6 +171,8 @@ public class ConceptMapValidator extends BaseValidator {
for (CMCodingValidationRequest cv : batch) {
if (cv.getResult().getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
warning(errors, "2023-09-06", IssueType.BUSINESSRULE, cv.getStack(), cv.getResult().isOk(), I18nConstants.CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM, cv.getCoding().getSystem(), cv.getCoding().getCode(), cv.getVsObj().getUrl());
} else if (cv.getResult().getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED_VERSION) {
warning(errors, "2023-09-06", IssueType.BUSINESSRULE, cv.getStack(), cv.getResult().isOk(), I18nConstants.CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM_VERSION, cv.getCoding().getSystem(), cv.getCoding().getCode(), cv.getVsObj().getUrl(), cv.getResult().getVersion());
} else if (cv.getCoding().getVersion() == null) {
ok = rule(errors, "2023-09-06", IssueType.BUSINESSRULE, cv.getStack(), cv.getResult().isOk(), I18nConstants.CONCEPTMAP_VS_INVALID_CONCEPT_CODE, cv.getCoding().getSystem(), cv.getCoding().getCode(), cv.getVsObj().getUrl()) && ok;
} else {

View File

@ -736,13 +736,18 @@ public class StructureMapValidator extends BaseValidator {
type = "string";
break;
default:
rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TRANSFORM_NOT_CHECKED, transform);
ok = false;
warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TRANSFORM_NOT_CHECKED, transform);
// ok = false;
}
if (vn != null && type != null) {
StructureDefinition sdt = this.context.fetchTypeDefinition(type);
vn.setType(ruleInfo.getMaxCount(), sdt, sdt.getSnapshot().getElementFirstRep(), null); // may overwrite
if (sdt != null) {
vn.setType(ruleInfo.getMaxCount(), sdt, sdt.getSnapshot().getElementFirstRep(), null); // may overwrite
} else {
ok = false;
rule(errors, "2023-07-30", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TYPE_UNKNOWN, type);
}
}
return ok;
}
@ -905,8 +910,8 @@ public class StructureMapValidator extends BaseValidator {
}
break;
default:
rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TRANSFORM_NOT_CHECKED, transform);
ok = false;
warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TRANSFORM_NOT_CHECKED, transform);
// ok = false;
}
if (vn != null) {
// it's just a warning: maybe this'll work out at run time?

View File

@ -7545,6 +7545,52 @@ v: {
"system" : "http://loinc.org",
"version" : "2.77",
"server" : "http://tx-dev.fhir.org/r4",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://loinc.org",
"code" : "58410-2",
"display" : "CBC panel - Blood by Automated count"
}, "valueSet" :null, "langs":"", "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: {
"display" : "CBC panel - Blood by Automated count",
"code" : "58410-2",
"system" : "http://loinc.org",
"version" : "2.77",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://loinc.org",
"code" : "58410-2"
}, "url": "http://hl7.org/fhir/ValueSet/report-codes--0", "version": "4.0.1", "langs":"", "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: {
"display" : "CBC panel - Blood by Automated count",
"code" : "58410-2",
"system" : "http://loinc.org",
"version" : "2.77",
"server" : "http://tx-dev.fhir.org/r4",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"

View File

@ -14,14 +14,14 @@
HAPI FHIR
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.19-SNAPSHOT</version>
<version>6.3.20-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<commons_compress_version>1.26.0</commons_compress_version>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.5.17-SNAPSHOT</validator_test_case_version>
<validator_test_case_version>1.5.17</validator_test_case_version>
<jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>