Merge pull request #1368 from hapifhir/2023-07-gg-obligations-fixes
2023 07 gg obligations fixes
This commit is contained in:
commit
aa0aa65d61
|
@ -42,35 +42,60 @@ public class ICFImporter {
|
|||
cs.setCopyright("© World Health Organization 2022\r\nSome rights reserved. This work is available under the Creative Commons Attribution-NoDerivatives 3.0 IGO license (CC BY-ND 3.0 IGO further specified at [[https://icd.who.int/en/docs/ICD11-license.pdf]]). \r\nUnder the terms of this license, you may copy and redistribute the work, provided the work is appropriately cited, as indicated below. In any use of this work, there should be no suggestion that WHO endorses any specific organization, products or services. The use of the WHO logo is not permitted. This license does not allow you to produce adaptations of the work (including translations) without permission from WHO.\r\nAny mediation relating to disputes arising under the license shall be conducted in accordance with the mediation rules of the World Intellectual Property Organization.\r\nThis FHIR version of ICD-11 was generated to support the FHIR Community. The definitive version of ICD-11 is available from [[https://icd.who.int/browse11/l-m/en]].\r\n");
|
||||
|
||||
cs.addProperty().setCode("icd11-uri").setDescription("Entity URI to map to ICD_11").setType(PropertyType.CODE);
|
||||
cs.addProperty().setCode("kind").setDescription("Whether concept is chapter, block, or category").setType(PropertyType.CODE);
|
||||
cs.addProperty().setCode("IsResidual").setDescription("True if the concept is not completely defined by ICD-11").setType(PropertyType.BOOLEAN);
|
||||
Map<Integer, ConceptDefinitionComponent> codes = new HashMap<>();
|
||||
Map<String, ConceptDefinitionComponent> codes = new HashMap<>();
|
||||
|
||||
int lastChapter = 0;
|
||||
int lastBlock = 0;
|
||||
while (csv.line()) {
|
||||
String kind = csv.cell("ClassKind");
|
||||
String code = csv.cell("Code");
|
||||
if (!Utilities.noString(code)) {
|
||||
ConceptDefinitionComponent c = new ConceptDefinitionComponent();
|
||||
c.setCode(code);
|
||||
c.setDisplay(fixDisplay(csv.cell("Title")));
|
||||
c.addProperty().setCode("uri").setValue(new CodeType(csv.cell("Linearization (release) URI")));
|
||||
String b = csv.cell("IsResidual").toLowerCase();
|
||||
if (!"false".equals(b)) {
|
||||
c.addProperty().setCode("IsResidual").setValue(new BooleanType(b));
|
||||
if (Utilities.noString(code)) {
|
||||
code = csv.cell("BlockId");
|
||||
}
|
||||
ConceptDefinitionComponent c = new ConceptDefinitionComponent();
|
||||
c.setCode(code);
|
||||
c.setDisplay(fixDisplay(csv.cell("Title")));
|
||||
c.addProperty().setCode("uri").setValue(new CodeType(csv.cell("Linearization (release) URI")));
|
||||
c.addProperty().setCode("kind").setValue(new CodeType(kind));
|
||||
String b = csv.cell("IsResidual").toLowerCase();
|
||||
if (!"false".equals(b)) {
|
||||
c.addProperty().setCode("IsResidual").setValue(new BooleanType(b));
|
||||
}
|
||||
int level = Integer.parseInt(csv.cell("DepthInKind"));
|
||||
String id = kind+"-"+level;
|
||||
String parentId = null;
|
||||
switch (kind) {
|
||||
case "chapter":
|
||||
parentId = null;
|
||||
lastChapter = level;
|
||||
break;
|
||||
case "block":
|
||||
parentId = "chapter-"+lastChapter;
|
||||
lastBlock = level;
|
||||
break;
|
||||
case "category":
|
||||
parentId = "block-"+lastBlock;
|
||||
break;
|
||||
}
|
||||
Integer level = Integer.parseInt(csv.cell("DepthInKind"));
|
||||
if (level == 1) {
|
||||
cs.getConcept().add(c);
|
||||
} else {
|
||||
ConceptDefinitionComponent p = codes.get(level -1);
|
||||
p.getConcept().add(c);
|
||||
}
|
||||
codes.put(level, c);
|
||||
for (int i = level + 1; i < 100; i++) {
|
||||
if (codes.containsKey(i)) {
|
||||
codes.remove(i);
|
||||
}
|
||||
if (level > 1) {
|
||||
parentId = kind+"-"+(level - 1);
|
||||
}
|
||||
System.out.println(code+" "+kind+" "+level+" "+id+" "+parentId+" ("+lastChapter+" "+lastBlock+")");
|
||||
if (parentId == null) {
|
||||
cs.getConcept().add(c);
|
||||
} else {
|
||||
ConceptDefinitionComponent p = codes.get(parentId);
|
||||
p.getConcept().add(c);
|
||||
}
|
||||
codes.put(id, c);
|
||||
for (int i = level + 1; i < 100; i++) {
|
||||
if (codes.containsKey(i)) {
|
||||
codes.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
csv.close();
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(dst), cs);
|
||||
|
|
|
@ -219,7 +219,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
"http://hl7.org/fhir/tools/StructureDefinition/obligation-profile",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status-reason",
|
||||
ToolingExtensions.EXT_SUMMARY,
|
||||
ToolingExtensions.EXT_OBLIGATION);
|
||||
ToolingExtensions.EXT_OBLIGATION_CORE,
|
||||
ToolingExtensions.EXT_OBLIGATION_TOOLS);
|
||||
|
||||
|
||||
public IWorkerContext getContext() {
|
||||
|
@ -2205,7 +2206,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
for (ElementDefinition ed : obligationProfileElements) {
|
||||
for (Extension ext : ed.getExtension()) {
|
||||
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
|
||||
if (Utilities.existsInList(ext.getUrl(), ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
base.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
|
@ -2279,13 +2280,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
for (Extension ext : source.getExtension()) {
|
||||
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
|
||||
if (Utilities.existsInList(ext.getUrl(), ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
for (ElementDefinition ed : obligationProfileElements) {
|
||||
for (Extension ext : ed.getExtension()) {
|
||||
if (ToolingExtensions.EXT_OBLIGATION.equals(ext.getUrl())) {
|
||||
if (Utilities.existsInList(ext.getUrl(), ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
|||
import org.hl7.fhir.instance.model.api.IDomainResource;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.StandardsStatus;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
@ -434,8 +435,14 @@ public void checkNoModifiers(String noun, String verb) throws FHIRException {
|
|||
getExtension().add(ex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean hasExtension(String... theUrls) {
|
||||
for (Extension next : getExtension()) {
|
||||
if (Utilities.existsInList(next.getUrl(), theUrls)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasExtension(String url) {
|
||||
for (Extension e : getExtension())
|
||||
|
@ -487,6 +494,18 @@ public void checkNoModifiers(String noun, String verb) throws FHIRException {
|
|||
}
|
||||
return Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
|
||||
public List<Extension> getExtensionsByUrl(String... theUrls) {
|
||||
|
||||
ArrayList<Extension> retVal = new ArrayList<>();
|
||||
for (Extension next : getExtension()) {
|
||||
if (Utilities.existsInList(next.getUrl(), theUrls)) {
|
||||
retVal.add(next);
|
||||
}
|
||||
}
|
||||
return java.util.Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of modifier extensions from this element which have the given URL. Note that
|
||||
|
|
|
@ -407,6 +407,28 @@ public abstract class Element extends Base implements IBaseHasExtensions, IBaseE
|
|||
return java.util.Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
public List<Extension> getExtensionsByUrl(String... theUrls) {
|
||||
|
||||
ArrayList<Extension> retVal = new ArrayList<>();
|
||||
for (Extension next : getExtension()) {
|
||||
if (Utilities.existsInList(next.getUrl(), theUrls)) {
|
||||
retVal.add(next);
|
||||
}
|
||||
}
|
||||
return java.util.Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasExtension(String... theUrls) {
|
||||
for (Extension next : getExtension()) {
|
||||
if (Utilities.existsInList(next.getUrl(), theUrls)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an true if this element has an extension that matchs the given URL.
|
||||
*
|
||||
|
|
|
@ -12860,7 +12860,6 @@ If a pattern[x] is declared on a repeating element, the pattern applies to all r
|
|||
return t;
|
||||
}
|
||||
|
||||
|
||||
// end addition
|
||||
|
||||
}
|
||||
|
|
|
@ -42,11 +42,11 @@ public class ObligationsRenderer {
|
|||
public static class ObligationDetail {
|
||||
private String code;
|
||||
private List<String> elementIds = new ArrayList<>();
|
||||
private String actorId;
|
||||
private String actor;
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private String filter;
|
||||
private String filterDesc;
|
||||
private String filterDoco;
|
||||
private List<UsageContext> usage = new ArrayList<>();
|
||||
private boolean isUnchanged = false;
|
||||
private boolean matched = false;
|
||||
|
@ -58,11 +58,17 @@ public class ObligationsRenderer {
|
|||
|
||||
public ObligationDetail(Extension ext) {
|
||||
this.code = ext.getExtensionString("code");
|
||||
this.actorId = ext.getExtensionString("actorId");
|
||||
this.actor = ext.getExtensionString("actor");
|
||||
if (this.actor == null) {
|
||||
this.actor = ext.getExtensionString("actorId");
|
||||
}
|
||||
this.doco = ext.getExtensionString("documentation");
|
||||
this.docoShort = ext.getExtensionString("shortDoco");
|
||||
this.filter = ext.getExtensionString("filter");
|
||||
this.filterDesc = ext.getExtensionString("filter-desc");
|
||||
this.filterDoco = ext.getExtensionString("filterDocumentation");
|
||||
if (this.filterDoco == null) {
|
||||
this.filterDoco = ext.getExtensionString("filter-desc");
|
||||
}
|
||||
for (Extension usage : ext.getExtensionsByUrl("usage")) {
|
||||
this.usage.add(usage.getValueUsageContext());
|
||||
}
|
||||
|
@ -101,11 +107,11 @@ public class ObligationsRenderer {
|
|||
isUnchanged = true;
|
||||
isUnchanged = isUnchanged && ((code==null && compare.code==null) || code.equals(compare.code));
|
||||
isUnchanged = elementIds.equals(compare.elementIds);
|
||||
isUnchanged = isUnchanged && ((actorId==null && compare.actorId==null) || actorId.equals(compare.actorId));
|
||||
isUnchanged = isUnchanged && ((actor==null && compare.actor==null) || actor.equals(compare.actor));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((filter==null && compare.filter==null) || filter.equals(compare.filter));
|
||||
isUnchanged = isUnchanged && ((filterDesc==null && compare.filterDesc==null) || filterDesc.equals(compare.filterDesc));
|
||||
isUnchanged = isUnchanged && ((filterDoco==null && compare.filterDoco==null) || filterDoco.equals(compare.filterDoco));
|
||||
isUnchanged = isUnchanged && ((usage==null && compare.usage==null) || usage.equals(compare.usage));
|
||||
return isUnchanged;
|
||||
}
|
||||
|
@ -119,7 +125,7 @@ public class ObligationsRenderer {
|
|||
}
|
||||
|
||||
public String getFilterDesc() {
|
||||
return filterDesc;
|
||||
return filterDoco;
|
||||
}
|
||||
|
||||
public String getFilter() {
|
||||
|
@ -131,11 +137,11 @@ public class ObligationsRenderer {
|
|||
}
|
||||
|
||||
public boolean hasActor() {
|
||||
return actorId != null;
|
||||
return actor != null;
|
||||
}
|
||||
|
||||
public boolean hasActor(String id) {
|
||||
return id.equals(actorId);
|
||||
return id.equals(actor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,7 +344,7 @@ public class ObligationsRenderer {
|
|||
boolean filter = false;
|
||||
boolean elementId = false;
|
||||
for (ObligationDetail binding : obligations) {
|
||||
actor = actor || binding.actorId!=null || (binding.compare!=null && binding.compare.actorId !=null);
|
||||
actor = actor || binding.actor!=null || (binding.compare!=null && binding.compare.actor !=null);
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || !binding.usage.isEmpty() || (binding.compare!=null && !binding.compare.usage.isEmpty());
|
||||
filter = filter || binding.filter != null || (binding.compare!=null && binding.compare.filter!=null);
|
||||
|
@ -383,29 +389,29 @@ public class ObligationsRenderer {
|
|||
}
|
||||
if (actor) {
|
||||
|
||||
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, ob.actorId);
|
||||
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, ob.actor);
|
||||
ActorDefinition compAd = null;
|
||||
if (ob.compare!=null && ob.compare.actorId!=null) {
|
||||
compAd = context.getContext().fetchResource(ActorDefinition.class, ob.compare.actorId);
|
||||
if (ob.compare!=null && ob.compare.actor!=null) {
|
||||
compAd = context.getContext().fetchResource(ActorDefinition.class, ob.compare.actor);
|
||||
}
|
||||
|
||||
XhtmlNode actorId = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.actorId.equals(ob.compare.actorId))
|
||||
if (ob.compare!=null && ob.actor.equals(ob.compare.actor))
|
||||
actorId.style(STYLE_UNCHANGED);
|
||||
if (ad != null && ad.hasWebPath()) {
|
||||
actorId.ah(ad.getWebPath(), ob.actorId).tx(ad.present());
|
||||
actorId.ah(ad.getWebPath(), ob.actor).tx(ad.present());
|
||||
} else if (ad != null) {
|
||||
actorId.span(null, ob.actorId).tx(ad.present());
|
||||
actorId.span(null, ob.actor).tx(ad.present());
|
||||
}
|
||||
|
||||
if (ob.compare!=null && ob.compare.actorId!=null && !ob.actorId.equals(ob.compare.actorId)) {
|
||||
if (ob.compare!=null && ob.compare.actor!=null && !ob.actor.equals(ob.compare.actor)) {
|
||||
actorId.br();
|
||||
actorId = actorId.span(STYLE_REMOVED, null);
|
||||
if (compAd != null) {
|
||||
if (compAd.hasWebPath()) {
|
||||
actorId.ah(compAd.getWebPath(), ob.compare.actorId).tx(compAd.present());
|
||||
actorId.ah(compAd.getWebPath(), ob.compare.actor).tx(compAd.present());
|
||||
} else {
|
||||
actorId.span(null, ob.compare.actorId).tx(compAd.present());
|
||||
actorId.span(null, ob.compare.actor).tx(compAd.present());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -457,8 +463,8 @@ public class ObligationsRenderer {
|
|||
|
||||
if (filter) {
|
||||
if (ob.filter != null) {
|
||||
String d = "<code>"+ob.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.filterDesc) : "");
|
||||
String oldD = ob.compare==null ? null : "<code>"+ob.compare.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.compare.filterDesc) : "");
|
||||
String d = "<code>"+ob.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.filterDoco) : "");
|
||||
String oldD = ob.compare==null ? null : "<code>"+ob.compare.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.compare.filterDoco) : "");
|
||||
tr.td().style("font-size: 11px").innerHTML(compareHtml(d, oldD));
|
||||
} else {
|
||||
tr.td().style("font-size: 11px");
|
||||
|
|
|
@ -500,9 +500,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
|
||||
private void scanObligations(Set<String> cols, List<ElementDefinition> list, ElementDefinition ed) {
|
||||
|
||||
for (Extension ob : ed.getExtensionsByUrl("http://hl7.org/fhir/tools/StructureDefinition/obligation")) {
|
||||
if (ob.hasExtension("actor")) {
|
||||
for (Extension a : ob.getExtensionsByUrl("actor")) {
|
||||
for (Extension ob : ed.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
if (ob.hasExtension("actor", "actorId")) {
|
||||
for (Extension a : ob.getExtensionsByUrl("actor", "actorId")) {
|
||||
cols.add(a.getValueCanonicalType().primitiveValue());
|
||||
}
|
||||
} else
|
||||
|
@ -838,11 +838,11 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
checkForNoChange(element.getIsModifierElement(), gc.addStyledText(translate("sd.table", "This element is a modifier element"), "?!", null, null, null, false));
|
||||
}
|
||||
if (element != null) {
|
||||
if (element.getMustSupport() && element.hasExtension(ToolingExtensions.EXT_OBLIGATION)) {
|
||||
if (element.getMustSupport() && element.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
checkForNoChange(element.getMustSupportElement(), gc.addStyledText(translate("sd.table", "This element has obligations and must be supported"), "SO", "white", "red", null, false));
|
||||
} else if (element.getMustSupport()) {
|
||||
checkForNoChange(element.getMustSupportElement(), gc.addStyledText(translate("sd.table", "This element must be supported"), "S", "white", "red", null, false));
|
||||
} else if (element != null && element.hasExtension(ToolingExtensions.EXT_OBLIGATION)) {
|
||||
} else if (element != null && element.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
checkForNoChange(element.getMustSupportElement(), gc.addStyledText(translate("sd.table", "This element has obligations"), "O", "white", "red", null, false));
|
||||
}
|
||||
}
|
||||
|
@ -1384,11 +1384,11 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
ObligationsRenderer obr = new ObligationsRenderer(corePath, profile, definition.getPath(), rc, null, this);
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_OBLIGATION)) {
|
||||
obr.seeObligations(definition.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION));
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
obr.seeObligations(definition.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS));
|
||||
}
|
||||
if (!definition.getPath().contains(".") && profile.hasExtension(ToolingExtensions.EXT_OBLIGATION)) {
|
||||
obr.seeObligations(profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION));
|
||||
if (!definition.getPath().contains(".") && profile.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
obr.seeObligations(profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS));
|
||||
}
|
||||
obr.renderTable(gen, c);
|
||||
|
||||
|
|
|
@ -247,7 +247,8 @@ public class ToolingExtensions {
|
|||
public static final String WEB_BINDING_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/StructureDefinition-binding-style.html";
|
||||
public static final String EXT_IGDEP_COMMENT = "http://hl7.org/fhir/tools/StructureDefinition/implementationguide-dependency-comment";
|
||||
public static final String EXT_XPATH_CONSTRAINT = "http://hl7.org/fhir/4.0/StructureDefinition/extension-ElementDefinition.constraint.xpath";
|
||||
public static final String EXT_OBLIGATION = "http://hl7.org/fhir/tools/StructureDefinition/obligation";
|
||||
public static final String EXT_OBLIGATION_TOOLS = "http://hl7.org/fhir/tools/StructureDefinition/obligation";
|
||||
public static final String EXT_OBLIGATION_CORE = "http://hl7.org/fhir/StructureDefinition/obligation";
|
||||
public static final String EXT_NO_BINDING = "http://hl7.org/fhir/tools/StructureDefinition/no-binding";
|
||||
;
|
||||
|
||||
|
|
|
@ -112,6 +112,9 @@ public class Utilities {
|
|||
return false;
|
||||
}
|
||||
String value = string.startsWith("-") ? string.substring(1) : string;
|
||||
if (Utilities.noString(value)) {
|
||||
return false;
|
||||
}
|
||||
for (char next : value.toCharArray()) {
|
||||
if (!Character.isDigit(next)) {
|
||||
return false;
|
||||
|
|
|
@ -946,6 +946,7 @@ public class I18nConstants {
|
|||
public static final String ED_INVARIANT_DIFF_NO_SOURCE = "ED_INVARIANT_DIFF_NO_SOURCE";
|
||||
public static final String FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT = "FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT";
|
||||
public static final String FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT = "FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT";
|
||||
public static final String ED_INVARIANT_KEY_ALREADY_USED = "ED_INVARIANT_KEY_ALREADY_USED";
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -970,10 +970,11 @@ QUESTIONNAIRE_Q_ITEM_DERIVED_ANSWER_OPTIONS_NEW = The item with linkId ''{1}'' f
|
|||
PRIMITIVE_MUSTHAVEVALUE_MESSAGE = The element definition ``{0}`` in the profile ''{1}'' requires that a value be present in this element
|
||||
PRIMITIVE_VALUE_ALTERNATIVES_MESSAGE_one = The element definition ``{0}`` in the profile ''{1}'' requires that if a value is not present, the extension ''{2}'' must be present
|
||||
PRIMITIVE_VALUE_ALTERNATIVES_MESSAGE_other = The element definition ``{0}`` in the profile ''{1}'' requires that if a value is not present, one of the extensions ''{2}'' must be present
|
||||
ED_INVARIANT_NO_KEY = The invariant has no key, so the content cannot be validated
|
||||
ED_INVARIANT_NO_EXPRESSION = The invariant ''{0}'' has no computable expression, so validators will not be able to check it
|
||||
ED_INVARIANT_EXPRESSION_CONFLICT = The invariant ''{0}'' has an expression ''{1}'', which differs from the earlier expression provided of ''{2}'' (invariants are allowed to repeat, but cannot differ)
|
||||
ED_INVARIANT_EXPRESSION_ERROR = Error in invariant ''{0}'' with expression ''{1}'': {2}
|
||||
ED_INVARIANT_NO_KEY = The constraint has no key, so the content cannot be validated
|
||||
ED_INVARIANT_KEY_ALREADY_USED = The constraint key ''{0}'' already exists in the base profile ''{1}''
|
||||
ED_INVARIANT_NO_EXPRESSION = The constraint ''{0}'' has no computable expression, so validators will not be able to check it
|
||||
ED_INVARIANT_EXPRESSION_CONFLICT = The constraint ''{0}'' has an expression ''{1}'', which differs from the earlier expression provided of ''{2}'' (invariants are allowed to repeat, but cannot differ)
|
||||
ED_INVARIANT_EXPRESSION_ERROR = Error in constraint ''{0}'' with expression ''{1}'': {2}
|
||||
SNAPSHOT_IS_EMPTY = The snapshot for the profile ''{0}'' is empty (which should not happen)
|
||||
TERMINOLOGY_TX_HINT = {1}
|
||||
TERMINOLOGY_TX_WARNING = {1}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
|||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
|
@ -131,10 +132,10 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
boolean logical = "logical".equals(src.getNamedChildValue("kind"));
|
||||
boolean constraint = "constraint".equals(src.getNamedChildValue("derivation"));
|
||||
for (Element differential : differentials) {
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url")) && ok;
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url"), base) && ok;
|
||||
}
|
||||
for (Element snapshotE : snapshots) {
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url")) && ok;
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url"), base) && ok;
|
||||
}
|
||||
|
||||
// obligation profile support
|
||||
|
@ -217,7 +218,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
NodeStack stack = push.push(child, c, null, null);
|
||||
if (child.getName().equals("extension")) {
|
||||
String url = child.getNamedChildValue("url");
|
||||
if ("http://hl7.org/fhir/tools/StructureDefinition/obligation".equals(url)) {
|
||||
if (Utilities.existsInList(url, ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
// this is ok, and it doesn't matter what's in the obligation
|
||||
} else {
|
||||
ok = false;
|
||||
|
@ -332,19 +333,19 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl) {
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, StructureDefinition base) {
|
||||
Map<String, String> invariantMap = new HashMap<>();
|
||||
boolean ok = true;
|
||||
List<Element> elements = elementList.getChildrenByName("element");
|
||||
int cc = 0;
|
||||
for (Element element : elements) {
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl) && ok;
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, base) && ok;
|
||||
cc++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl) {
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl, StructureDefinition base) {
|
||||
boolean ok = true;
|
||||
boolean typeMustSupport = false;
|
||||
String path = element.getNamedChildValue("path");
|
||||
|
@ -472,13 +473,14 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
List<Element> constraints = element.getChildrenByName("constraint");
|
||||
int cc = 0;
|
||||
for (Element invariant : constraints) {
|
||||
ok = validateElementDefinitionInvariant(errors, invariant, stack.push(invariant, cc, null, null), invariantMap, elements, element, element.getNamedChildValue("path"), rootPath, profileUrl, snapshot) && ok;
|
||||
ok = validateElementDefinitionInvariant(errors, invariant, stack.push(invariant, cc, null, null), invariantMap, elements, element, element.getNamedChildValue("path"), rootPath, profileUrl, snapshot, base) && ok;
|
||||
cc++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateElementDefinitionInvariant(List<ValidationMessage> errors, Element invariant, NodeStack stack, Map<String, String> invariantMap, List<Element> elements, Element element, String path, String rootPath, String profileUrl, boolean snapshot) {
|
||||
private boolean validateElementDefinitionInvariant(List<ValidationMessage> errors, Element invariant, NodeStack stack, Map<String, String> invariantMap, List<Element> elements, Element element,
|
||||
String path, String rootPath, String profileUrl, boolean snapshot, StructureDefinition base) {
|
||||
boolean ok = true;
|
||||
String key = invariant.getNamedChildValue("key");
|
||||
String expression = invariant.getNamedChildValue("expression");
|
||||
|
@ -525,13 +527,26 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ok = rule(errors, "2023-07-27", IssueType.INVALID, stack, source == null || source.equals(profileUrl), I18nConstants.ED_INVARIANT_DIFF_NO_SOURCE, key, source);
|
||||
ok = rule(errors, "2023-07-27", IssueType.INVALID, stack, source == null || source.equals(profileUrl), I18nConstants.ED_INVARIANT_DIFF_NO_SOURCE, key, source) &&
|
||||
rule(errors, "2023-07-27", IssueType.INVALID, stack, !haseHasInvariant(base, key), I18nConstants.ED_INVARIANT_KEY_ALREADY_USED, key, base.getVersionedUrl());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean haseHasInvariant(StructureDefinition base, String key) {
|
||||
for (ElementDefinition ed : base.getSnapshot().getElement()) {
|
||||
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
|
||||
if (key.equals(inv.getKey())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String tail(Element te, Element newte) {
|
||||
String p = te.getNamedChildValue("path");
|
||||
String pn = newte.getNamedChildValue("path");
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -20,7 +20,7 @@
|
|||
<properties>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.3.18</validator_test_case_version>
|
||||
<validator_test_case_version>1.3.19-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.15.2</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue