Merge pull request #1636 from hapifhir/FixObligationRendering

Corrected ObligationsRenderer to handle multiple actors and multiple …
This commit is contained in:
Grahame Grieve 2024-06-07 04:34:43 +10:00 committed by GitHub
commit 24b7d2db39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 185 additions and 134 deletions

View File

@ -1657,7 +1657,7 @@ public class ProfileUtilities extends TranslatingUtilities {
r.getCells().add(gen.new Cell("", "", "Extension", null, null));
r.setIcon("icon_"+m+"extension_complex.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_COMPLEX);
for (ElementDefinition c : children) {
ved = getValueFor(ed, c);
ElementDefinition ued = getUrlFor(ed, c);
@ -1697,7 +1697,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
c.addPiece(gen.new Piece("br")).addPiece(gen.new Piece(null, describeExtensionContext(ed), null));
r.getCells().add(c);
try {
return gen.generate(model, corePath, 0, outputTracker);
} catch (org.hl7.fhir.exceptions.FHIRException e) {
@ -3484,7 +3484,7 @@ public class ProfileUtilities extends TranslatingUtilities {
TableModel model = initSpanningTable(gen, "", false, profile.getId());
Set<String> processed = new HashSet<String>();
SpanEntry span = buildSpanningTable("(focus)", "", profile, processed, onlyConstraints, constraintPrefix);
genSpanEntry(gen, model.getRows(), span);
return gen.generate(model, "", 0, outputTracker);
}

View File

@ -1,33 +1,33 @@
package org.hl7.fhir.dstu3.utils;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@ -3236,7 +3236,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
case INEXACT : return "><";
case UNMATCHED : return "-";
case DISJOINT : return "!=";
case NULL: return null;
case NULL: return null;
default: return "?";
}
}
@ -3701,13 +3701,6 @@ public class NarrativeGenerator implements INarrativeGenerator {
return null;
}
public boolean generate(ResourceContext rcontext, StructureDefinition sd, java.util.Set<String> outputTracker) throws EOperationOutcome, FHIRException, IOException {
ProfileUtilities pu = new ProfileUtilities(context, null, pkp);
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
x.getChildNodes().add(pu.generateTable(definitionsTarget, sd, true, destDir, false, sd.getId(), false, corePath, "", false, false, outputTracker));
inject(sd, x, NarrativeStatus.GENERATED);
return true;
}
public boolean generate(ResourceContext rcontext, ImplementationGuide ig) throws EOperationOutcome, FHIRException, IOException {
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
x.h2().addText(ig.getName());

View File

@ -1253,7 +1253,7 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
public XhtmlNode renderStructure(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(session.getI18n(), Utilities.path("[tmp]", "compare"), false, true);
TableModel model = gen.initComparisonTable(corePath, id);
genElementComp(null /* come back to this later */, gen, model.getRows(), comp.combined, corePath, prefix, null, true);
genElementComp(null /* come back to this later */, null /* come back to this later */, gen, model.getRows(), comp.combined, corePath, prefix, null, true);
return gen.generate(model, prefix, 0, null);
}
@ -1268,7 +1268,7 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
return sdr.generateTable(corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "i");
}
private void genElementComp(String defPath, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinitionNode> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
private void genElementComp(String defPath, String anchorPrefix, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinitionNode> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
Row originalRow = slicingRow;
Row typesRow = null;
@ -1334,19 +1334,19 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
nc = sdrRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName, null);
}
if (combined.hasLeft()) {
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0), leftColor);
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList<ElementDefinition>()), leftColor);
} else {
frame(spacers(row, 4, gen), leftColor);
}
if (combined.hasRight()) {
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0), rightColor);
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList<ElementDefinition>()), rightColor);
} else {
frame(spacers(row, 4, gen), rightColor);
}
row.getCells().add(cellForMessages(gen, combined.getMessages()));
for (StructuralMatch<ElementDefinitionNode> child : children) {
genElementComp(defPath, gen, row.getSubRows(), child, corePath, prefix, originalRow, false);
genElementComp(defPath, anchorPrefix, gen, row.getSubRows(), child, corePath, prefix, originalRow, false);
}
}

View File

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.fhir.ucum.Canonical;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.profile.BindingResolution;
@ -14,6 +15,7 @@ import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.ActorDefinition;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ElementDefinition;
@ -40,9 +42,9 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNodeList;
public class ObligationsRenderer {
public static class ObligationDetail {
private String code;
private List<String> codes = new ArrayList<>();
private List<String> elementIds = new ArrayList<>();
private String actor;
private List<CanonicalType> actors = new ArrayList<>();
private String doco;
private String docoShort;
private String filter;
@ -57,10 +59,11 @@ public class ObligationsRenderer {
private int count = 1;
public ObligationDetail(Extension ext) {
this.code = ext.getExtensionString("code");
this.actor = ext.getExtensionString("actor");
if (this.actor == null) {
this.actor = ext.getExtensionString("actorId");
for (Extension e: ext.getExtensionsByUrl("code")) {
codes.add(e.getValueStringType().toString());
}
for (Extension e: ext.getExtensionsByUrl("actor")) {
actors.add(e.getValueCanonicalType());
}
this.doco = ext.getExtensionString("documentation");
this.docoShort = ext.getExtensionString("shortDoco");
@ -80,7 +83,7 @@ public class ObligationsRenderer {
private String getKey() {
// Todo: Consider extending this with content from usageContext if purpose isn't sufficiently differentiating
return code + Integer.toString(count);
return String.join(",", codes) + Integer.toString(count);
}
private void incrementCount() {
@ -96,8 +99,11 @@ public class ObligationsRenderer {
public String getDoco(boolean full) {
return full ? doco : docoShort;
}
public String getCode() {
return code;
public String getCodes() {
return String.join(",", codes);
}
public List<String> getCodeList() {
return new ArrayList<String>(codes);
}
public boolean unchanged() {
if (!isUnchanged)
@ -105,9 +111,9 @@ public class ObligationsRenderer {
if (compare==null)
return true;
isUnchanged = true;
isUnchanged = isUnchanged && ((code==null && compare.code==null) || code.equals(compare.code));
isUnchanged = isUnchanged && ((codes.isEmpty() && compare.codes.isEmpty()) || codes.equals(compare.codes));
isUnchanged = elementIds.equals(compare.elementIds);
isUnchanged = isUnchanged && ((actor==null && compare.actor==null) || actor.equals(compare.actor));
isUnchanged = isUnchanged && ((actors.isEmpty() && compare.actors.isEmpty()) || actors.equals(compare.actors));
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));
@ -136,12 +142,16 @@ public class ObligationsRenderer {
return usage;
}
public boolean hasActor() {
return actor != null;
public boolean hasActors() {
return !actors.isEmpty();
}
public boolean hasActor(String id) {
return id.equals(actor);
for (CanonicalType actor: actors) {
if (actor.getValue().equals(id))
return true;
}
return false;
}
}
@ -276,24 +286,24 @@ public class ObligationsRenderer {
return abr;
}
public String render() throws IOException {
public String render(String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
if (obligations.isEmpty()) {
return "";
} else {
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
tbl.attribute("class", "grid");
renderTable(tbl.getChildNodes(), true);
renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements);
return new XhtmlComposer(false).compose(tbl);
}
}
public void renderTable(HierarchicalTableGenerator gen, Cell c) throws FHIRFormatError, DefinitionException, IOException {
public void renderTable(HierarchicalTableGenerator gen, Cell c, List<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
if (obligations.isEmpty()) {
return;
} else {
Piece piece = gen.new Piece("table").attr("class", "grid");
c.getPieces().add(piece);
renderTable(piece.getChildren(), false);
renderTable(piece.getChildren(), false, gen.getDefPath(), gen.getAnchorPrefix(), inScopeElements);
}
}
@ -313,10 +323,21 @@ public class ObligationsRenderer {
}
private void renderObligationLI(XhtmlNodeList children, ObligationDetail ob) throws IOException {
renderCode(children, ob.getCode());
if (ob.hasFilter() || ob.hasUsage()) {
renderCodes(children, ob.getCodeList());
if (ob.hasFilter() || ob.hasUsage() || !ob.elementIds.isEmpty()) {
children.tx(" (");
boolean ffirst = !ob.hasFilter();
boolean firstEid = true;
for (String eid: ob.elementIds) {
if (firstEid) {
children.span().i().tx("Elements: ");
firstEid = false;
} else
children.tx(", ");
String trimmedElement = eid.substring(eid.indexOf(".")+ 1);
children.tx(trimmedElement);
}
if (ob.hasFilter()) {
children.span(null, ob.getFilterDesc()).code().tx(ob.getFilter());
}
@ -337,20 +358,25 @@ public class ObligationsRenderer {
}
public void renderTable(List<XhtmlNode> children, boolean fullDoco) throws FHIRFormatError, DefinitionException, IOException {
public void renderTable(List<XhtmlNode> children, boolean fullDoco, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
boolean doco = false;
boolean usage = false;
boolean actor = false;
boolean filter = false;
boolean elementId = false;
for (ObligationDetail binding : obligations) {
actor = actor || binding.actor!=null || (binding.compare!=null && binding.compare.actor !=null);
actor = actor || !binding.actors.isEmpty() || (binding.compare!=null && !binding.compare.actors.isEmpty());
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);
elementId = elementId || !binding.elementIds.isEmpty() || (binding.compare!=null && !binding.compare.elementIds.isEmpty());
}
List<String> inScopePaths = new ArrayList<>();
for (ElementDefinition e: inScopeElements) {
inScopePaths.add(e.getPath());
}
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
children.add(tr);
tr.td().style("font-size: 11px").b().tx(context.formatPhrase(RenderingContext.GENERAL_OBLIG));
@ -379,43 +405,52 @@ public class ObligationsRenderer {
children.add(tr);
XhtmlNode code = tr.td().style("font-size: 11px");
if (ob.compare!=null && ob.code.equals(ob.compare.code))
if (ob.compare!=null && ob.getCodes().equals(ob.compare.getCodes()))
code.style("font-color: darkgray");
renderCode(code.getChildNodes(), ob.code);
if (ob.compare!=null && ob.compare.code != null && !ob.code.equals(ob.compare.code)) {
renderCodes(code.getChildNodes(), ob.getCodeList());
if (ob.compare!=null && !ob.compare.getCodeList().isEmpty() && !ob.getCodes().equals(ob.compare.getCodes())) {
code.br();
code = code.span(STYLE_UNCHANGED, null);
renderCode(code.getChildNodes(), ob.compare.code);
renderCodes(code.getChildNodes(), ob.compare.getCodeList());
}
if (actor) {
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, ob.actor);
ActorDefinition compAd = null;
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.actors.isEmpty() || ob.compare.actors.isEmpty()) {
boolean firstActor = false;
for (CanonicalType anActor : ob.actors) {
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, anActor.toString());
boolean existingActor = ob.compare != null && ob.compare.actors.contains(anActor);
if (!firstActor) {
actorId.br();
firstActor = true;
}
if (!existingActor)
actorId.style(STYLE_UNCHANGED);
}
XhtmlNode actorId = tr.td().style("font-size: 11px");
if (ob.compare!=null && ob.actor.equals(ob.compare.actor))
actorId.style(STYLE_UNCHANGED);
if (ad != null && ad.hasWebPath()) {
actorId.ah(ad.getWebPath(), ob.actor).tx(ad.present());
} else if (ad != null) {
actorId.span(null, ob.actor).tx(ad.present());
}
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.actor).tx(compAd.present());
} else {
actorId.span(null, ob.compare.actor).tx(compAd.present());
if (ob.compare != null) {
for (CanonicalType compActor : ob.compare.actors) {
if (!ob.actors.contains(compActor)) {
ActorDefinition compAd = context.getContext().fetchResource(ActorDefinition.class, compActor.toString());
if (!firstActor) {
actorId.br();
firstActor = true;
}
actorId = actorId.span(STYLE_REMOVED, null);
if (compAd.hasWebPath()) {
actorId.ah(compAd.getWebPath(), compActor.toString()).tx(compAd.present());
} else {
actorId.span(null, compActor.toString()).tx(compAd.present());
}
}
}
}
}
if (elementId) {
XhtmlNode elementIds = tr.td().style("font-size: 11px");
if (ob.compare!=null && ob.elementIds.equals(ob.compare.elementIds))
@ -423,10 +458,13 @@ public class ObligationsRenderer {
for (String eid : ob.elementIds) {
elementIds.sep(", ");
ElementDefinition ed = profile.getSnapshot().getElementById(eid);
if (ed != null) {
elementIds.ah("#"+eid).tx(ed.getName());
boolean inScope = inScopePaths.contains(ed.getPath());
String name = eid.substring(eid.indexOf(".") + 1);
if (ed != null && inScope) {
String link = defPath + "#" + anchorPrefix + eid;
elementIds.ah(link).tx(name);
} else {
elementIds.code().tx(eid);
elementIds.code().tx(name);
}
}
@ -491,10 +529,10 @@ public class ObligationsRenderer {
return newS + "<br/><span style=\"" + STYLE_REMOVED + "\">" + oldS + "</span>";
}
private void renderCode(XhtmlNodeList children, String codeExpr) {
if (codeExpr != null) {
private void renderCodes(XhtmlNodeList children, List<String> codes) {
if (!codes.isEmpty()) {
boolean first = true;
String[] codes = codeExpr.split("\\+");
for (String code : codes) {
if (first) first = false; else children.tx(" & ");
int i = code.indexOf(":");
@ -507,7 +545,7 @@ public class ObligationsRenderer {
CodeResolution cr = this.cr.resolveCode("http://hl7.org/fhir/tools/CodeSystem/obligation", code);
code = code.replace("will-", "").replace("can-", "");
if (cr.getLink() != null) {
children.ah(cr.getLink(), cr.getHint()).tx(code);
children.ah(cr.getLink(), cr.getHint()).tx(code);
} else {
children.span(null, cr.getHint()).tx(code);
}

View File

@ -549,7 +549,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
public XhtmlNode generateTable(String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath,
boolean logicalModel, boolean allInvariants, Set<String> outputTracker, boolean mustSupport, RenderingContext rc, String anchorPrefix) throws IOException, FHIRException {
assert(diff != snapshot);// check it's ok to get rid of one of these
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true);
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defFile, anchorPrefix);
List<ElementDefinition> list;
if (diff)
@ -815,7 +815,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
genElementObligations(gen, element, columns, row, corePath, profile);
break;
case SUMMARY:
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0);
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0, defPath, anchorPrefix, all);
break;
}
if (element.hasSlicing()) {
@ -1078,7 +1078,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
public List<Cell> genElementCells(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath,
String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef,
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis) throws IOException {
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
List<Cell> res = new ArrayList<>();
Cell gc = gen.new Cell();
row.getCells().add(gc);
@ -1121,7 +1121,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
if (extDefn == null) {
res.add(genCardinality(gen, element, row, hasDef, used, null));
res.add(addCell(row, gen.new Cell(null, null, "?gen-e1? "+element.getType().get(0).getProfile(), null, null)));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
} else {
String name = element.hasSliceName() ? element.getSliceName() : urltail(eurl);
nameCell.getPieces().get(0).setText(name);
@ -1134,7 +1134,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
else // if it's complex, we just call it nothing
// genTypes(gen, row, extDefn.getSnapshot().getElement().get(0), profileBaseFileName, profile);
res.add(addCell(row, gen.new Cell(null, null, "("+(context.formatPhrase(RenderingContext.STRUC_DEF_COMPLEX))+")", null, null)));
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc));
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
}
} else {
res.add(genCardinality(gen, element, row, hasDef, used, null));
@ -1142,7 +1142,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
res.add(addCell(row, gen.new Cell()));
else
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
}
}
} else if (element != null) {
@ -1151,7 +1151,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
else
res.add(addCell(row, gen.new Cell()));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
}
return res;
}
@ -1309,10 +1309,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
}
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException {
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc);
}
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException {
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, new ArrayList<ElementDefinition>());
}
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List<ElementDefinition> inScopeElements) throws IOException, FHIRException {
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, inScopeElements);
}
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List<ElementDefinition> inScopeElements) throws IOException, FHIRException {
Cell c = gen.new Cell();
row.getCells().add(c);
@ -1691,7 +1695,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
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);
obr.renderTable(gen, c, inScopeElements);
if (definition.hasMaxLength() && definition.getMaxLength()!=0) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
@ -3046,7 +3050,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
public XhtmlNode generateSpanningTable(StructureDefinition profile, String imageFolder, boolean onlyConstraints, String constraintPrefix, Set<String> outputTracker) throws IOException, FHIRException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, false, true);
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, false, true, "", "");
TableModel model = initSpanningTable(gen, "", false, profile.getId());
Set<String> processed = new HashSet<String>();
SpanEntry span = buildSpanningTable("(focus)", "", profile, processed, onlyConstraints, constraintPrefix);
@ -3149,8 +3153,8 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
return first ? null : x;
}
public XhtmlNode generateExtensionTable(String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set<String> outputTracker, RenderingContext rc) throws IOException, FHIRException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true);
public XhtmlNode generateExtensionTable(String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set<String> outputTracker, RenderingContext rc, String defPath, String anchorPrefix) throws IOException, FHIRException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defPath, anchorPrefix);
TableModel model = gen.initNormalTable(corePath, false, true, ed.getId()+(full ? "f" : "n"), true, TableGenerationMode.XHTML);
boolean deep = false;
@ -3211,7 +3215,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
r1.getCells().add(gen.new Cell(null, null, describeCardinality(c, null, new UnusedTracker()), null, null));
genTypes(gen, r1, ved, defFile, ed, corePath, imagePath, false, false);
r1.setIcon("icon_"+m+"extension_simple.png", context.formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_SIMPLE));
generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc);
generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc, new ArrayList<ElementDefinition>());
}
}
} else {
@ -3324,7 +3328,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
if (isProfiledExtension(ec)) {
StructureDefinition extDefn = context.getContext().fetchResource(StructureDefinition.class, ec.getType().get(0).getProfile().get(0).getValue());
if (extDefn == null) {
generateElementInner(t, sd, ec, 1, null, compareElement, null, false);
generateElementInner(t, sd, ec, 1, null, compareElement, null, false, "", anchorPrefix, elements);
} else {
ElementDefinition valueDefn = getExtensionValueDefinition(extDefn);
ElementDefinition compareValueDefn = null;
@ -3332,15 +3336,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
StructureDefinition compareExtDefn = context.getContext().fetchResource(StructureDefinition.class, compareElement.getType().get(0).getProfile().get(0).getValue());
compareValueDefn = getExtensionValueDefinition(extDefn);
} catch (Exception except) {}
generateElementInner(t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false);
generateElementInner(t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false, "", anchorPrefix, elements);
// generateElementInner(b, extDefn, extDefn.getSnapshot().getElement().get(0), valueDefn == null ? 2 : 3, valueDefn);
}
} else {
while (!dstack.isEmpty() && !isParent(dstack.peek(), ec)) {
finish(t, sd, dstack.pop(), mode);
finish(t, sd, dstack.pop(), mode, "", anchorPrefix);
}
dstack.push(ec);
generateElementInner(t, sd, ec, mode, null, compareElement, null, false);
generateElementInner(t, sd, ec, mode, null, compareElement, null, false, "", anchorPrefix, elements);
if (ec.hasSlicing()) {
generateSlicing(t, sd, ec, ec.getSlicing(), compareElement, mode, false);
}
@ -3350,12 +3354,12 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
i++;
}
while (!dstack.isEmpty()) {
finish(t, sd, dstack.pop(), mode);
finish(t, sd, dstack.pop(), mode, "", anchorPrefix);
}
finish(t, sd, null, mode);
finish(t, sd, null, mode, "", anchorPrefix);
}
private void finish(XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode) throws FHIRException, IOException {
private void finish(XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode, String defPath, String anchorPrefix) throws FHIRException, IOException {
for (Base b : VersionComparisonAnnotation.getDeleted(ed == null ? sd : ed, "element")) {
ElementDefinition ec = (ElementDefinition) b;
@ -3365,7 +3369,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
sp.span("color: grey", null).tx("--");
sp.b().tx(". "+title);
generateElementInner(t, sd, ec, mode, null, null, null, true);
generateElementInner(t, sd, ec, mode, null, null, null, true, defPath, anchorPrefix, new ArrayList<ElementDefinition>());
if (ec.hasSlicing()) {
generateSlicing(t, sd, ec, ec.getSlicing(), null, mode, true);
}
@ -3685,7 +3689,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
return "color:DarkGray;text-decoration:line-through";
}
private void generateElementInner(XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough) throws FHIRException, IOException {
private void generateElementInner(XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws FHIRException, IOException {
boolean root = !d.getPath().contains(".");
boolean slicedExtension = d.hasSliceName() && (d.getPath().endsWith(".extension") || d.getPath().endsWith(".modifierExtension"));
// int slicedExtensionMode = (mode == GEN_MODE_KEY) && slicedExtension ? GEN_MODE_SNAP : mode; // see ProfileUtilities.checkExtensionDoco / Task 3970
@ -3779,7 +3783,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
tableRow(tbl, context.formatPhrase(RenderingContext.STRUC_DEF_COMP_PROF), "http://hl7.org/fhir/extensions/StructureDefinition-structuredefinition-compliesWithProfile.html", strikethrough,
renderCanonicalListExt(context.formatPhrase(RenderingContext.STRUC_DEF_PROF_COMP)+" ", sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_COMPLIES_WITH_PROFILE)));
}
tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(d, root, sd));
tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(d, root, sd, defPath, anchorPrefix, inScopeElements));
if (d.hasExtension(ToolingExtensions.EXT_EXTENSION_STYLE)) {
String es = d.getExtensionString(ToolingExtensions.EXT_EXTENSION_STYLE);
@ -3981,7 +3985,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
}
}
private XhtmlNode describeObligations(ElementDefinition d, boolean root, StructureDefinition sdx) throws IOException {
private XhtmlNode describeObligations(ElementDefinition d, boolean root, StructureDefinition sdx, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
XhtmlNode ret = new XhtmlNode(NodeType.Element, "div");
ObligationsRenderer obr = new ObligationsRenderer(corePath, sdx, d.getPath(), context, hostMd, this);
obr.seeObligations(d.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS));
@ -4011,7 +4015,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
}
if (obr.hasObligations()) {
XhtmlNode tbl = ret.table("grid");
obr.renderTable(tbl.getChildNodes(), true);
obr.renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements);
if (tbl.isEmpty()) {
ret.remove(tbl);
}

View File

@ -120,7 +120,7 @@ public class HierarchicalTableGenerator {
public static final int CONTINUE_SLICE = 5;
private static final String BACKGROUND_ALT_COLOR = "#F7F7F7";
public static boolean ACTIVE_TABLES = false;
public enum TextAlignment {
LEFT, CENTER, RIGHT;
}
@ -617,7 +617,9 @@ public class HierarchicalTableGenerator {
private String dest;
private boolean makeTargets;
private String defPath = "";
private String anchorPrefix = "";
/**
* There are circumstances where the table has to present in the absence of a stable supporting infrastructure.
* and the file paths cannot be guaranteed. For these reasons, you can tell the builder to inline all the graphics
@ -629,11 +631,6 @@ public class HierarchicalTableGenerator {
private TableGenerationMode mode;
private RenderingI18nContext i18n;
public HierarchicalTableGenerator(RenderingI18nContext i18n) {
super();
this.i18n = i18n;
}
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics) {
super();
this.i18n = i18n;
@ -643,6 +640,14 @@ public class HierarchicalTableGenerator {
checkSetup();
}
public String getDefPath() {
return defPath;
}
public String getAnchorPrefix() {
return anchorPrefix;
}
private void checkSetup() {
if (dest == null) {
throw new Error("what");
@ -650,6 +655,17 @@ public class HierarchicalTableGenerator {
}
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets, String defPath, String anchorPrefix) {
super();
this.i18n = i18n;
this.dest = dest;
this.inLineGraphics = inlineGraphics;
this.makeTargets = makeTargets;
this.defPath = defPath;
this.anchorPrefix = anchorPrefix;
checkSetup();
}
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets) {
super();
this.i18n = i18n;