start building the renderer package
This commit is contained in:
parent
ef2f9e01c7
commit
37d4994c8f
|
@ -87,7 +87,7 @@ import org.hl7.fhir.r5.model.UriType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer;
|
import org.hl7.fhir.r5.renderers.TerminologyRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hl7.fhir.r5.terminologies;
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -10,12 +10,12 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap;
|
import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
import org.hl7.fhir.r5.model.Enumeration;
|
import org.hl7.fhir.r5.model.Enumeration;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
|
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
|
@ -25,34 +25,46 @@ import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public class CodeSystemRenderer extends TerminologyRenderer {
|
public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
|
public CodeSystemRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeSystemRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||||
|
super(context, rcontext);
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> codeSystemPropList = new ArrayList<>();
|
private List<String> codeSystemPropList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param mode - whether we are rendering for a resource directly, or for an IG
|
|
||||||
* @param context - common services (terminology server, code system cache etc)
|
|
||||||
* @param markdown - markdown processing engine of the correct sort for the version applicable
|
|
||||||
* @param prefix - the path to the base FHIR specification
|
|
||||||
* @param lang - the language to use (null for the default)
|
|
||||||
*/
|
|
||||||
public CodeSystemRenderer(TerminologyRendererMode mode, IWorkerContext context, MarkDownProcessor markdown, String prefix, String lang) {
|
|
||||||
super(mode, context, markdown, prefix, lang);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getCodeSystemPropList() {
|
public List<String> getCodeSystemPropList() {
|
||||||
return codeSystemPropList;
|
return codeSystemPropList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean generate(XhtmlNode x, CodeSystem cs, boolean header) throws FHIRFormatError, DefinitionException, IOException {
|
public void render(CodeSystem cs) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, cs);
|
||||||
|
inject(cs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, CodeSystem cs) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
return render(x, cs, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, CodeSystem cs, boolean header) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
boolean hasExtensions = false;
|
boolean hasExtensions = false;
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
|
@ -71,15 +83,23 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
return hasExtensions;
|
return hasExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, CodeSystem cs) {
|
||||||
|
x.tx(display(cs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(CodeSystem cs) {
|
||||||
|
return cs.present();
|
||||||
|
}
|
||||||
|
|
||||||
private void generateFilters(XhtmlNode x, CodeSystem cs) {
|
private void generateFilters(XhtmlNode x, CodeSystem cs) {
|
||||||
if (cs.hasFilter()) {
|
if (cs.hasFilter()) {
|
||||||
x.para().b().tx(context.translator().translate("xhtml-gen-cs", "Filters", lang));
|
x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Filters", getContext().getLang()));
|
||||||
XhtmlNode tbl = x.table("grid");
|
XhtmlNode tbl = x.table("grid");
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Code", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Code", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Description", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Description", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "operator", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "operator", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Value", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Value", getContext().getLang()));
|
||||||
for (CodeSystemFilterComponent f : cs.getFilter()) {
|
for (CodeSystemFilterComponent f : cs.getFilter()) {
|
||||||
tr = tbl.tr();
|
tr = tbl.tr();
|
||||||
tr.td().tx(f.getCode());
|
tr.td().tx(f.getCode());
|
||||||
|
@ -99,16 +119,16 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
hasRendered = hasRendered || !p.getCode().equals(ToolingExtensions.getPresentation(p, p.getCodeElement()));
|
hasRendered = hasRendered || !p.getCode().equals(ToolingExtensions.getPresentation(p, p.getCodeElement()));
|
||||||
}
|
}
|
||||||
|
|
||||||
x.para().b().tx(context.translator().translate("xhtml-gen-cs", "Properties", lang));
|
x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Properties", getContext().getLang()));
|
||||||
XhtmlNode tbl = x.table("grid");
|
XhtmlNode tbl = x.table("grid");
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
if (hasRendered) {
|
if (hasRendered) {
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Name", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Name", getContext().getLang()));
|
||||||
}
|
}
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Code", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Code", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "URL", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "URL", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Description", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Description", getContext().getLang()));
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Type", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Type", getContext().getLang()));
|
||||||
for (PropertyComponent p : cs.getProperty()) {
|
for (PropertyComponent p : cs.getProperty()) {
|
||||||
tr = tbl.tr();
|
tr = tbl.tr();
|
||||||
if (hasRendered) {
|
if (hasRendered) {
|
||||||
|
@ -125,13 +145,13 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
XhtmlNode p = x.para();
|
XhtmlNode p = x.para();
|
||||||
if (cs.getContent() == CodeSystemContentMode.COMPLETE)
|
if (cs.getContent() == CodeSystemContentMode.COMPLETE)
|
||||||
p.tx(context.translator().translateAndFormat("xhtml-gen-cs", lang, "This code system %s defines the following codes", cs.getUrl())+":");
|
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system %s defines the following codes", cs.getUrl())+":");
|
||||||
else if (cs.getContent() == CodeSystemContentMode.EXAMPLE)
|
else if (cs.getContent() == CodeSystemContentMode.EXAMPLE)
|
||||||
p.tx(context.translator().translateAndFormat("xhtml-gen-cs", lang, "This code system %s defines many codes, of which the following are some examples", cs.getUrl())+":");
|
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system %s defines many codes, of which the following are some examples", cs.getUrl())+":");
|
||||||
else if (cs.getContent() == CodeSystemContentMode.FRAGMENT )
|
else if (cs.getContent() == CodeSystemContentMode.FRAGMENT )
|
||||||
p.tx(context.translator().translateAndFormat("xhtml-gen-cs", lang, "This code system %s defines many codes, of which the following are a subset", cs.getUrl())+":");
|
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system %s defines many codes, of which the following are a subset", cs.getUrl())+":");
|
||||||
else if (cs.getContent() == CodeSystemContentMode.NOTPRESENT ) {
|
else if (cs.getContent() == CodeSystemContentMode.NOTPRESENT ) {
|
||||||
p.tx(context.translator().translateAndFormat("xhtml-gen-cs", lang, "This code system %s defines many codes, but they are not represented here", cs.getUrl()));
|
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system %s defines many codes, but they are not represented here", cs.getUrl()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
XhtmlNode t = x.table( "codes");
|
XhtmlNode t = x.table( "codes");
|
||||||
|
@ -212,7 +232,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
if (Utilities.existsInList(uri, "http://hl7.org/fhir/concept-properties") || codeSystemPropList.contains(uri)) {
|
if (Utilities.existsInList(uri, "http://hl7.org/fhir/concept-properties") || codeSystemPropList.contains(uri)) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
CodeSystem cs = context.fetchCodeSystem(uri);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(uri);
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -298,12 +318,12 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
if (c != null &&
|
if (c != null &&
|
||||||
c.hasDefinitionElement()) {
|
c.hasDefinitionElement()) {
|
||||||
if (lang == null) {
|
if (getContext().getLang() == null) {
|
||||||
if (hasMarkdownInDefinitions(cs))
|
if (hasMarkdownInDefinitions(cs))
|
||||||
addMarkdown(td, c.getDefinition());
|
addMarkdown(td, c.getDefinition());
|
||||||
else
|
else
|
||||||
td.addText(c.getDefinition());
|
td.addText(c.getDefinition());
|
||||||
} else if (lang.equals("*")) {
|
} else if (getContext().getLang().equals("*")) {
|
||||||
boolean sl = false;
|
boolean sl = false;
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue()))
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue()))
|
||||||
|
@ -315,11 +335,11 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
td.addText(cd.getLanguage()+": "+cd.getValue());
|
td.addText(cd.getLanguage()+": "+cd.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (lang.equals(cs.getLanguage()) || (lang.equals("en") && !cs.hasLanguage())) {
|
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
|
||||||
td.addText(c.getDefinition());
|
td.addText(c.getDefinition());
|
||||||
} else {
|
} else {
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && cd.getLanguage().equals(lang)) {
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) {
|
||||||
td.addText(cd.getValue());
|
td.addText(cd.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +349,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
Boolean b = CodeSystemUtilities.isDeprecated(cs, c);
|
Boolean b = CodeSystemUtilities.isDeprecated(cs, c);
|
||||||
if (b != null && b) {
|
if (b != null && b) {
|
||||||
smartAddText(td, context.translator().translate("xhtml-gen-cs", "Deprecated", lang));
|
smartAddText(td, getContext().getWorker().translator().translate("xhtml-gen-cs", "Deprecated", getContext().getLang()));
|
||||||
hasExtensions = true;
|
hasExtensions = true;
|
||||||
if (ToolingExtensions.hasExtension(c, ToolingExtensions.EXT_REPLACED_BY)) {
|
if (ToolingExtensions.hasExtension(c, ToolingExtensions.EXT_REPLACED_BY)) {
|
||||||
Coding cc = (Coding) ToolingExtensions.getExtension(c, ToolingExtensions.EXT_REPLACED_BY).getValue();
|
Coding cc = (Coding) ToolingExtensions.getExtension(c, ToolingExtensions.EXT_REPLACED_BY).getValue();
|
||||||
|
@ -351,10 +371,10 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
String bc = ext.hasValue() ? ext.getValue().primitiveValue() : null;
|
String bc = ext.hasValue() ? ext.getValue().primitiveValue() : null;
|
||||||
Map<String, String> translations = ToolingExtensions.getLanguageTranslations(ext.getValue());
|
Map<String, String> translations = ToolingExtensions.getLanguageTranslations(ext.getValue());
|
||||||
|
|
||||||
if (lang == null) {
|
if (getContext().getLang() == null) {
|
||||||
if (bc != null)
|
if (bc != null)
|
||||||
td.addText(bc);
|
td.addText(bc);
|
||||||
} else if (lang.equals("*")) {
|
} else if (getContext().getLang().equals("*")) {
|
||||||
boolean sl = false;
|
boolean sl = false;
|
||||||
for (String l : translations.keySet())
|
for (String l : translations.keySet())
|
||||||
if (bc == null || !bc.equalsIgnoreCase(translations.get(l)))
|
if (bc == null || !bc.equalsIgnoreCase(translations.get(l)))
|
||||||
|
@ -369,14 +389,14 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
td.addText(l+": "+translations.get(l));
|
td.addText(l+": "+translations.get(l));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (lang.equals(cs.getLanguage()) || (lang.equals("en") && !cs.hasLanguage())) {
|
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
|
||||||
if (bc != null)
|
if (bc != null)
|
||||||
td.addText(bc);
|
td.addText(bc);
|
||||||
} else {
|
} else {
|
||||||
if (bc != null)
|
if (bc != null)
|
||||||
translations.put(cs.getLanguage("en"), bc);
|
translations.put(cs.getLanguage("en"), bc);
|
||||||
for (String l : translations.keySet()) {
|
for (String l : translations.keySet()) {
|
||||||
if (l.equals(lang)) {
|
if (l.equals(getContext().getLang())) {
|
||||||
td.addText(translations.get(l));
|
td.addText(translations.get(l));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +436,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
first = false;
|
first = false;
|
||||||
XhtmlNode span = td.span(null, mapping.comp.hasRelationship() ? mapping.comp.getRelationship().toCode() : "");
|
XhtmlNode span = td.span(null, mapping.comp.hasRelationship() ? mapping.comp.getRelationship().toCode() : "");
|
||||||
span.addText(getCharForRelationship(mapping.comp));
|
span.addText(getCharForRelationship(mapping.comp));
|
||||||
a = td.ah(prefix+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode()));
|
a = td.ah(getContext().getPrefix()+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode()));
|
||||||
a.addText(mapping.comp.getCode());
|
a.addText(mapping.comp.getCode());
|
||||||
if (!Utilities.noString(mapping.comp.getComment()))
|
if (!Utilities.noString(mapping.comp.getComment()))
|
||||||
td.i().tx("("+mapping.comp.getComment()+")");
|
td.i().tx("("+mapping.comp.getComment()+")");
|
||||||
|
@ -456,9 +476,9 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
public void renderDisplayName(ConceptDefinitionComponent c, CodeSystem cs, XhtmlNode td) {
|
public void renderDisplayName(ConceptDefinitionComponent c, CodeSystem cs, XhtmlNode td) {
|
||||||
if (c.hasDisplayElement()) {
|
if (c.hasDisplayElement()) {
|
||||||
if (lang == null) {
|
if (getContext().getLang() == null) {
|
||||||
td.addText(c.getDisplay());
|
td.addText(c.getDisplay());
|
||||||
} else if (lang.equals("*")) {
|
} else if (getContext().getLang().equals("*")) {
|
||||||
boolean sl = false;
|
boolean sl = false;
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue()))
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue()))
|
||||||
|
@ -470,11 +490,11 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
td.addText(cd.getLanguage()+": "+cd.getValue());
|
td.addText(cd.getLanguage()+": "+cd.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (lang.equals(cs.getLanguage()) || (lang.equals("en") && !cs.hasLanguage())) {
|
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
|
||||||
td.addText(c.getDisplay());
|
td.addText(c.getDisplay());
|
||||||
} else {
|
} else {
|
||||||
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
|
||||||
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && cd.getLanguage().equals(lang)) {
|
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) {
|
||||||
td.addText(cd.getValue());
|
td.addText(cd.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hl7.fhir.r5.terminologies;
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -8,50 +8,54 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap;
|
import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
import org.hl7.fhir.r5.model.ContactDetail;
|
import org.hl7.fhir.r5.model.ContactDetail;
|
||||||
import org.hl7.fhir.r5.model.ContactPoint;
|
import org.hl7.fhir.r5.model.ContactPoint;
|
||||||
|
import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.OtherElementComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.OtherElementComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
|
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship;
|
import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship;
|
||||||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.r5.utils.NarrativeGenerator.ResourceContext;
|
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public class ConceptMapRenderer extends TerminologyRenderer {
|
public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
/**
|
public ConceptMapRenderer(RenderingContext context) {
|
||||||
*
|
super(context);
|
||||||
* @param mode - whether we are rendering for a resource directly, or for an IG
|
|
||||||
* @param context - common services (terminology server, code system cache etc)
|
|
||||||
* @param markdown - markdown processing engine of the correct sort for the version applicable
|
|
||||||
* @param prefix - the path to the base FHIR specification
|
|
||||||
* @param lang - the language to use (null for the default)
|
|
||||||
*/
|
|
||||||
public ConceptMapRenderer(TerminologyRendererMode mode, IWorkerContext context, MarkDownProcessor markdown, String prefix, String lang) {
|
|
||||||
super(mode, context, markdown, prefix, lang);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean generate(ResourceContext rcontext, ConceptMap cm, XhtmlNode x) throws FHIRFormatError, DefinitionException, IOException {
|
public ConceptMapRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||||
|
super(context, rcontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(ConceptMap cm) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, cm);
|
||||||
|
inject(cm, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, ConceptMap cm) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
x.h2().addText(cm.getName()+" ("+cm.getUrl()+")");
|
x.h2().addText(cm.getName()+" ("+cm.getUrl()+")");
|
||||||
|
|
||||||
XhtmlNode p = x.para();
|
XhtmlNode p = x.para();
|
||||||
p.tx("Mapping from ");
|
p.tx("Mapping from ");
|
||||||
if (cm.hasSource())
|
if (cm.hasSource())
|
||||||
AddVsRef(rcontext, cm.getSource().primitiveValue(), p);
|
AddVsRef(cm.getSource().primitiveValue(), p);
|
||||||
else
|
else
|
||||||
p.tx("(not specified)");
|
p.tx("(not specified)");
|
||||||
p.tx(" to ");
|
p.tx(" to ");
|
||||||
if (cm.hasTarget())
|
if (cm.hasTarget())
|
||||||
AddVsRef(rcontext, cm.getTarget().primitiveValue(), p);
|
AddVsRef(cm.getTarget().primitiveValue(), p);
|
||||||
else
|
else
|
||||||
p.tx("(not specified)");
|
p.tx("(not specified)");
|
||||||
|
|
||||||
|
@ -89,9 +93,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
x.br();
|
x.br();
|
||||||
|
|
||||||
CodeSystem cs = context.fetchCodeSystem("http://hl7.org/fhir/concept-map-relationship");
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem("http://hl7.org/fhir/concept-map-relationship");
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
cs = context.fetchCodeSystem("http://hl7.org/fhir/concept-map-equivalence");
|
cs = getContext().getWorker().fetchCodeSystem("http://hl7.org/fhir/concept-map-equivalence");
|
||||||
String eqpath = cs == null ? null : cs.getUserString("path");
|
String eqpath = cs == null ? null : cs.getUserString("path");
|
||||||
|
|
||||||
for (ConceptMapGroupComponent grp : cm.getGroup()) {
|
for (ConceptMapGroupComponent grp : cm.getGroup()) {
|
||||||
|
@ -307,6 +311,14 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, ConceptMap cm) {
|
||||||
|
x.tx(display(cm));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(ConceptMap cm) {
|
||||||
|
return cm.present();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSameCodeAndDisplay(String code, String display) {
|
private boolean isSameCodeAndDisplay(String code, String display) {
|
||||||
String c = code.replace(" ", "").replace("-", "").toLowerCase();
|
String c = code.replace(" ", "").replace("-", "").toLowerCase();
|
||||||
String d = display.replace(" ", "").replace("-", "").toLowerCase();
|
String d = display.replace(" ", "").replace("-", "").toLowerCase();
|
||||||
|
@ -359,7 +371,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
public void renderCSDetailsLink(XhtmlNode tr, String url, boolean span2) {
|
public void renderCSDetailsLink(XhtmlNode tr, String url, boolean span2) {
|
||||||
CodeSystem cs;
|
CodeSystem cs;
|
||||||
XhtmlNode td;
|
XhtmlNode td;
|
||||||
cs = context.fetchCodeSystem(url);
|
cs = getContext().getWorker().fetchCodeSystem(url);
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
if (span2) {
|
if (span2) {
|
||||||
td.colspan("2");
|
td.colspan("2");
|
|
@ -0,0 +1,715 @@
|
||||||
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
|
import org.hl7.fhir.r5.model.Address;
|
||||||
|
import org.hl7.fhir.r5.model.Annotation;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
|
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
|
import org.hl7.fhir.r5.model.ContactPoint;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.Timing;
|
||||||
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
|
||||||
|
import org.hl7.fhir.r5.model.HumanName.NameUse;
|
||||||
|
import org.hl7.fhir.r5.model.Timing.EventTiming;
|
||||||
|
import org.hl7.fhir.r5.model.Timing.TimingRepeatComponent;
|
||||||
|
import org.hl7.fhir.r5.model.Timing.UnitsOfTime;
|
||||||
|
import org.hl7.fhir.r5.model.DataType;
|
||||||
|
import org.hl7.fhir.r5.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.r5.model.Enumeration;
|
||||||
|
import org.hl7.fhir.r5.model.HumanName;
|
||||||
|
import org.hl7.fhir.r5.model.Identifier;
|
||||||
|
import org.hl7.fhir.r5.model.Period;
|
||||||
|
import org.hl7.fhir.r5.model.Quantity;
|
||||||
|
import org.hl7.fhir.r5.model.Range;
|
||||||
|
import org.hl7.fhir.r5.model.SampledData;
|
||||||
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||||
|
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||||
|
|
||||||
|
public class DataRenderer {
|
||||||
|
|
||||||
|
// -- 1. context --------------------------------------------------------------
|
||||||
|
|
||||||
|
protected RenderingContext context;
|
||||||
|
|
||||||
|
public DataRenderer(RenderingContext context) {
|
||||||
|
super();
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- 2. Markdown support -------------------------------------------------------
|
||||||
|
|
||||||
|
protected void addMarkdown(XhtmlNode x, String text) throws FHIRFormatError, IOException, DefinitionException {
|
||||||
|
if (text != null) {
|
||||||
|
// 1. custom FHIR extensions
|
||||||
|
while (text.contains("[[[")) {
|
||||||
|
String left = text.substring(0, text.indexOf("[[["));
|
||||||
|
String link = text.substring(text.indexOf("[[[")+3, text.indexOf("]]]"));
|
||||||
|
String right = text.substring(text.indexOf("]]]")+3);
|
||||||
|
String url = link;
|
||||||
|
String[] parts = link.split("\\#");
|
||||||
|
StructureDefinition p = getContext().getWorker().fetchResource(StructureDefinition.class, parts[0]);
|
||||||
|
if (p == null)
|
||||||
|
p = getContext().getWorker().fetchTypeDefinition(parts[0]);
|
||||||
|
if (p == null)
|
||||||
|
p = getContext().getWorker().fetchResource(StructureDefinition.class, link);
|
||||||
|
if (p != null) {
|
||||||
|
url = p.getUserString("path");
|
||||||
|
if (url == null)
|
||||||
|
url = p.getUserString("filename");
|
||||||
|
} else
|
||||||
|
throw new DefinitionException("Unable to resolve markdown link "+link);
|
||||||
|
|
||||||
|
text = left+"["+link+"]("+url+")"+right;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. markdown
|
||||||
|
String s = getContext().getMarkdown().process(Utilities.escapeXml(text), "narrative generator");
|
||||||
|
XhtmlParser p = new XhtmlParser();
|
||||||
|
XhtmlNode m;
|
||||||
|
try {
|
||||||
|
m = p.parse("<div>"+s+"</div>", "div");
|
||||||
|
} catch (org.hl7.fhir.exceptions.FHIRFormatError e) {
|
||||||
|
throw new FHIRFormatError(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
x.getChildNodes().addAll(m.getChildNodes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void smartAddText(XhtmlNode p, String text) {
|
||||||
|
if (text == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String[] lines = text.split("\\r\\n");
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
p.br();
|
||||||
|
p.addText(lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- 3. Gener Purpose Terminology Support -----------------------------------------
|
||||||
|
|
||||||
|
public static String describeSystem(String system) {
|
||||||
|
if (system == null)
|
||||||
|
return "[not stated]";
|
||||||
|
if (system.equals("http://loinc.org"))
|
||||||
|
return "LOINC";
|
||||||
|
if (system.startsWith("http://snomed.info"))
|
||||||
|
return "SNOMED CT";
|
||||||
|
if (system.equals("http://www.nlm.nih.gov/research/umls/rxnorm"))
|
||||||
|
return "RxNorm";
|
||||||
|
if (system.equals("http://hl7.org/fhir/sid/icd-9"))
|
||||||
|
return "ICD-9";
|
||||||
|
if (system.equals("http://dicom.nema.org/resources/ontology/DCM"))
|
||||||
|
return "DICOM";
|
||||||
|
if (system.equals("http://unitsofmeasure.org"))
|
||||||
|
return "UCUM";
|
||||||
|
|
||||||
|
return system;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String makeAnchor(String codeSystem, String code) {
|
||||||
|
String s = codeSystem+'-'+code;
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
for (char c : s.toCharArray()) {
|
||||||
|
if (Character.isAlphabetic(c) || Character.isDigit(c) || c == '.')
|
||||||
|
b.append(c);
|
||||||
|
else
|
||||||
|
b.append('-');
|
||||||
|
}
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String lookupCode(String system, String code) {
|
||||||
|
ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), system, code, null);
|
||||||
|
|
||||||
|
if (t != null && t.getDisplay() != null)
|
||||||
|
return t.getDisplay();
|
||||||
|
else
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String describeLang(String lang) {
|
||||||
|
ValueSet v = getContext().getWorker().fetchResource(ValueSet.class, "http://hl7.org/fhir/ValueSet/languages");
|
||||||
|
if (v != null) {
|
||||||
|
ConceptReferenceComponent l = null;
|
||||||
|
for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) {
|
||||||
|
if (cc.getCode().equals(lang))
|
||||||
|
l = cc;
|
||||||
|
}
|
||||||
|
if (l == null) {
|
||||||
|
if (lang.contains("-"))
|
||||||
|
lang = lang.substring(0, lang.indexOf("-"));
|
||||||
|
for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) {
|
||||||
|
if (cc.getCode().equals(lang) || cc.getCode().startsWith(lang+"-"))
|
||||||
|
l = cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l != null) {
|
||||||
|
if (lang.contains("-"))
|
||||||
|
lang = lang.substring(0, lang.indexOf("-"));
|
||||||
|
String en = l.getDisplay();
|
||||||
|
String nativelang = null;
|
||||||
|
for (ConceptReferenceDesignationComponent cd : l.getDesignation()) {
|
||||||
|
if (cd.getLanguage().equals(lang))
|
||||||
|
nativelang = cd.getValue();
|
||||||
|
}
|
||||||
|
if (nativelang == null)
|
||||||
|
return en+" ("+lang+")";
|
||||||
|
else
|
||||||
|
return nativelang+" ("+en+", "+lang+")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isCanonical(String path) {
|
||||||
|
if (!path.endsWith(".url"))
|
||||||
|
return false;
|
||||||
|
StructureDefinition sd = getContext().getWorker().fetchTypeDefinition(path.substring(0, path.length()-4));
|
||||||
|
if (sd == null)
|
||||||
|
return false;
|
||||||
|
if (Utilities.existsInList(path.substring(0, path.length()-4), "CapabilityStatement", "StructureDefinition", "ImplementationGuide", "SearchParameter", "MessageDefinition", "OperationDefinition", "CompartmentDefinition", "StructureMap", "GraphDefinition",
|
||||||
|
"ExampleScenario", "CodeSystem", "ValueSet", "ConceptMap", "NamingSystem", "TerminologyCapabilities"))
|
||||||
|
return true;
|
||||||
|
return sd.getBaseDefinitionElement().hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-codegen-super");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- 4. Data type Rendering ----------------------------------------------
|
||||||
|
|
||||||
|
public static String display(IWorkerContext context, DataType type) {
|
||||||
|
return new DataRenderer(new RenderingContext(context, null, null, "", null, ResourceRendererMode.RESOURCE)).display(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(DataType type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(XhtmlNode x, DataType type) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderDateTime(XhtmlNode x, Base e) {
|
||||||
|
if (e.hasPrimitiveValue())
|
||||||
|
x.addText(((DateTimeType) e).toHumanDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderUri(XhtmlNode x, UriType uri) {
|
||||||
|
if (uri.getValue().startsWith("mailto:"))
|
||||||
|
x.ah(uri.getValue()).addText(uri.getValue().substring(7));
|
||||||
|
else
|
||||||
|
x.ah(uri.getValue()).addText(uri.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderUri(XhtmlNode x, UriType uri, String path, String id) {
|
||||||
|
String url = uri.getValue();
|
||||||
|
if (isCanonical(path)) {
|
||||||
|
CanonicalResource mr = getContext().getWorker().fetchResource(null, url);
|
||||||
|
if (mr != null) {
|
||||||
|
if (path.startsWith(mr.fhirType()+".") && mr.getId().equals(id)) {
|
||||||
|
url = null; // don't link to self whatever
|
||||||
|
} else if (mr.hasUserData("path"))
|
||||||
|
url = mr.getUserString("path");
|
||||||
|
} else if (!getContext().isCanonicalUrlsAsLinks())
|
||||||
|
url = null;
|
||||||
|
}
|
||||||
|
if (url == null)
|
||||||
|
x.b().tx(uri.getValue());
|
||||||
|
else if (uri.getValue().startsWith("mailto:"))
|
||||||
|
x.ah(uri.getValue()).addText(uri.getValue().substring(7));
|
||||||
|
else
|
||||||
|
x.ah(uri.getValue()).addText(uri.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderAnnotation(XhtmlNode x, Annotation annot) {
|
||||||
|
renderAnnotation(x, annot, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderAnnotation(XhtmlNode x, Annotation a, boolean showCodeDetails) throws FHIRException {
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
if (a.hasAuthor()) {
|
||||||
|
s.append("Author: ");
|
||||||
|
|
||||||
|
if (a.hasAuthorReference())
|
||||||
|
s.append(a.getAuthorReference().getReference());
|
||||||
|
else if (a.hasAuthorStringType())
|
||||||
|
s.append(a.getAuthorStringType().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (a.hasTimeElement()) {
|
||||||
|
if (s.length() > 0)
|
||||||
|
s.append("; ");
|
||||||
|
|
||||||
|
s.append("Made: ").append(a.getTimeElement().toHumanDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.hasText()) {
|
||||||
|
if (s.length() > 0)
|
||||||
|
s.append("; ");
|
||||||
|
|
||||||
|
s.append("Annotation: ").append(a.getText());
|
||||||
|
}
|
||||||
|
x.addText(s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCoding(XhtmlNode x, Coding c) {
|
||||||
|
renderCoding(x, c, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCoding(XhtmlNode x, Coding c, boolean showCodeDetails) {
|
||||||
|
String s = "";
|
||||||
|
if (c.hasDisplayElement())
|
||||||
|
s = c.getDisplay();
|
||||||
|
if (Utilities.noString(s))
|
||||||
|
s = lookupCode(c.getSystem(), c.getCode());
|
||||||
|
|
||||||
|
if (Utilities.noString(s))
|
||||||
|
s = c.getCode();
|
||||||
|
|
||||||
|
if (showCodeDetails) {
|
||||||
|
x.addText(s+" (Details: "+TerminologyRenderer.describeSystem(c.getSystem())+" code "+c.getCode()+" = '"+lookupCode(c.getSystem(), c.getCode())+"', stated as '"+c.getDisplay()+"')");
|
||||||
|
} else
|
||||||
|
x.span(null, "{"+c.getSystem()+" "+c.getCode()+"}").addText(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String displayCodeableConcept(CodeableConcept cc) {
|
||||||
|
String s = cc.getText();
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (c.hasDisplayElement()) {
|
||||||
|
s = c.getDisplay();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
// still? ok, let's try looking it up
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (c.hasCode() && c.hasSystem()) {
|
||||||
|
s = lookupCode(c.getSystem(), c.getCode());
|
||||||
|
if (!Utilities.noString(s))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
if (cc.getCoding().isEmpty())
|
||||||
|
s = "";
|
||||||
|
else
|
||||||
|
s = cc.getCoding().get(0).getCode();
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc) {
|
||||||
|
renderCodeableConcept(x, cc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc, boolean showCodeDetails) {
|
||||||
|
if (cc.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String s = cc.getText();
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (c.hasDisplayElement()) {
|
||||||
|
s = c.getDisplay();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
// still? ok, let's try looking it up
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (c.hasCodeElement() && c.hasSystemElement()) {
|
||||||
|
s = lookupCode(c.getSystem(), c.getCode());
|
||||||
|
if (!Utilities.noString(s))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utilities.noString(s)) {
|
||||||
|
if (cc.getCoding().isEmpty())
|
||||||
|
s = "";
|
||||||
|
else
|
||||||
|
s = cc.getCoding().get(0).getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showCodeDetails) {
|
||||||
|
x.addText(s+" ");
|
||||||
|
XhtmlNode sp = x.span("background: LightGoldenRodYellow", null);
|
||||||
|
sp.tx("(Details ");
|
||||||
|
boolean first = true;
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (first) {
|
||||||
|
sp.tx(": ");
|
||||||
|
first = false;
|
||||||
|
} else
|
||||||
|
sp.tx("; ");
|
||||||
|
sp.tx("{"+TerminologyRenderer.describeSystem(c.getSystem())+" code '"+c.getCode()+"' = '"+lookupCode(c.getSystem(), c.getCode())+(c.hasDisplay() ? "', given as '"+c.getDisplay()+"'}" : ""));
|
||||||
|
}
|
||||||
|
sp.tx(")");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
for (Coding c : cc.getCoding()) {
|
||||||
|
if (c.hasCodeElement() && c.hasSystemElement()) {
|
||||||
|
b.append("{"+c.getSystem()+" "+c.getCode()+"}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x.span(null, "Codes: "+b.toString()).addText(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayIdentifier(Identifier ii) {
|
||||||
|
String s = Utilities.noString(ii.getValue()) ? "?ngen-9?" : ii.getValue();
|
||||||
|
|
||||||
|
if (ii.hasType()) {
|
||||||
|
if (ii.getType().hasText())
|
||||||
|
s = ii.getType().getText()+" = "+s;
|
||||||
|
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay())
|
||||||
|
s = ii.getType().getCoding().get(0).getDisplay()+" = "+s;
|
||||||
|
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode())
|
||||||
|
s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getCode())+" = "+s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ii.hasUse())
|
||||||
|
s = s + " ("+ii.getUse().toString()+")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderIdentifier(XhtmlNode x, Identifier ii) {
|
||||||
|
x.addText(displayIdentifier(ii));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String displayHumanName(HumanName name) {
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
if (name.hasText())
|
||||||
|
s.append(name.getText());
|
||||||
|
else {
|
||||||
|
for (StringType p : name.getGiven()) {
|
||||||
|
s.append(p.getValue());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
if (name.hasFamily()) {
|
||||||
|
s.append(name.getFamily());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name.hasUse() && name.getUse() != NameUse.USUAL)
|
||||||
|
s.append("("+name.getUse().toString()+")");
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void renderHumanName(XhtmlNode x, HumanName name) {
|
||||||
|
x.addText(displayHumanName(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayAddress(Address address) {
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
if (address.hasText())
|
||||||
|
s.append(address.getText());
|
||||||
|
else {
|
||||||
|
for (StringType p : address.getLine()) {
|
||||||
|
s.append(p.getValue());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
if (address.hasCity()) {
|
||||||
|
s.append(address.getCity());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
if (address.hasState()) {
|
||||||
|
s.append(address.getState());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address.hasPostalCode()) {
|
||||||
|
s.append(address.getPostalCode());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address.hasCountry()) {
|
||||||
|
s.append(address.getCountry());
|
||||||
|
s.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (address.hasUse())
|
||||||
|
s.append("("+address.getUse().toString()+")");
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderAddress(XhtmlNode x, Address address) {
|
||||||
|
x.addText(displayAddress(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String displayContactPoint(ContactPoint contact) {
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
s.append(describeSystem(contact.getSystem()));
|
||||||
|
if (Utilities.noString(contact.getValue()))
|
||||||
|
s.append("-unknown-");
|
||||||
|
else
|
||||||
|
s.append(contact.getValue());
|
||||||
|
if (contact.hasUse())
|
||||||
|
s.append("("+contact.getUse().toString()+")");
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderContactPoint(XhtmlNode x, ContactPoint contact) {
|
||||||
|
x.addText(displayContactPoint(contact));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void addTelecom(XhtmlNode p, ContactPoint c) {
|
||||||
|
if (c.getSystem() == ContactPointSystem.PHONE) {
|
||||||
|
p.tx("Phone: "+c.getValue());
|
||||||
|
} else if (c.getSystem() == ContactPointSystem.FAX) {
|
||||||
|
p.tx("Fax: "+c.getValue());
|
||||||
|
} else if (c.getSystem() == ContactPointSystem.EMAIL) {
|
||||||
|
p.ah( "mailto:"+c.getValue()).addText(c.getValue());
|
||||||
|
} else if (c.getSystem() == ContactPointSystem.URL) {
|
||||||
|
if (c.getValue().length() > 30)
|
||||||
|
p.ah(c.getValue()).addText(c.getValue().substring(0, 30)+"...");
|
||||||
|
else
|
||||||
|
p.ah(c.getValue()).addText(c.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static String describeSystem(ContactPointSystem system) {
|
||||||
|
if (system == null)
|
||||||
|
return "";
|
||||||
|
switch (system) {
|
||||||
|
case PHONE: return "ph: ";
|
||||||
|
case FAX: return "fax: ";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String displayQuantity(Quantity q) {
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
|
||||||
|
s.append("(system = '").append(TerminologyRenderer.describeSystem(q.getSystem()))
|
||||||
|
.append("' code ").append(q.getCode())
|
||||||
|
.append(" = '").append(lookupCode(q.getSystem(), q.getCode())).append("')");
|
||||||
|
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderQuantity(XhtmlNode x, Quantity q) {
|
||||||
|
renderQuantity(x, q, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderQuantity(XhtmlNode x, Quantity q, boolean showCodeDetails) {
|
||||||
|
if (q.hasComparator())
|
||||||
|
x.addText(q.getComparator().toCode());
|
||||||
|
x.addText(q.getValue().toString());
|
||||||
|
if (q.hasUnit())
|
||||||
|
x.tx(" "+q.getUnit());
|
||||||
|
else if (q.hasCode())
|
||||||
|
x.tx(" "+q.getCode());
|
||||||
|
if (showCodeDetails && q.hasCode()) {
|
||||||
|
x.span("background: LightGoldenRodYellow", null).tx(" (Details: "+TerminologyRenderer.describeSystem(q.getSystem())+" code "+q.getCode()+" = '"+lookupCode(q.getSystem(), q.getCode())+"')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String displayRange(Range q) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
if (q.hasLow())
|
||||||
|
b.append(q.getLow().getValue().toString());
|
||||||
|
else
|
||||||
|
b.append("?");
|
||||||
|
b.append("-");
|
||||||
|
if (q.hasHigh())
|
||||||
|
b.append(q.getHigh().getValue().toString());
|
||||||
|
else
|
||||||
|
b.append("?");
|
||||||
|
if (q.getLow().hasUnit())
|
||||||
|
b.append(" "+q.getLow().getUnit());
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderRange(XhtmlNode x, Range q) {
|
||||||
|
if (q.hasLow())
|
||||||
|
x.addText(q.getLow().getValue().toString());
|
||||||
|
else
|
||||||
|
x.tx("?");
|
||||||
|
x.tx("-");
|
||||||
|
if (q.hasHigh())
|
||||||
|
x.addText(q.getHigh().getValue().toString());
|
||||||
|
else
|
||||||
|
x.tx("?");
|
||||||
|
if (q.getLow().hasUnit())
|
||||||
|
x.tx(" "+q.getLow().getUnit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String displayPeriod(Period p) {
|
||||||
|
String s = !p.hasStart() ? "?ngen-5?" : p.getStartElement().toHumanDisplay();
|
||||||
|
s = s + " --> ";
|
||||||
|
return s + (!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderPeriod(XhtmlNode x, Period p) {
|
||||||
|
x.addText(!p.hasStart() ? "??" : p.getStartElement().toHumanDisplay());
|
||||||
|
x.tx(" --> ");
|
||||||
|
x.addText(!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayTiming(Timing s) throws FHIRException {
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
if (s.hasCode())
|
||||||
|
b.append("Code: "+displayCodeableConcept(s.getCode()));
|
||||||
|
|
||||||
|
if (s.getEvent().size() > 0) {
|
||||||
|
CommaSeparatedStringBuilder c = new CommaSeparatedStringBuilder();
|
||||||
|
for (DateTimeType p : s.getEvent()) {
|
||||||
|
c.append(p.toHumanDisplay());
|
||||||
|
}
|
||||||
|
b.append("Events: "+ c.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.hasRepeat()) {
|
||||||
|
TimingRepeatComponent rep = s.getRepeat();
|
||||||
|
if (rep.hasBoundsPeriod() && rep.getBoundsPeriod().hasStart())
|
||||||
|
b.append("Starting "+rep.getBoundsPeriod().getStartElement().toHumanDisplay());
|
||||||
|
if (rep.hasCount())
|
||||||
|
b.append("Count "+Integer.toString(rep.getCount())+" times");
|
||||||
|
if (rep.hasDuration())
|
||||||
|
b.append("Duration "+rep.getDuration().toPlainString()+displayTimeUnits(rep.getPeriodUnit()));
|
||||||
|
|
||||||
|
if (rep.hasWhen()) {
|
||||||
|
String st = "";
|
||||||
|
if (rep.hasOffset()) {
|
||||||
|
st = Integer.toString(rep.getOffset())+"min ";
|
||||||
|
}
|
||||||
|
b.append("Do "+st);
|
||||||
|
for (Enumeration<EventTiming> wh : rep.getWhen())
|
||||||
|
b.append(displayEventCode(wh.getValue()));
|
||||||
|
} else {
|
||||||
|
String st = "";
|
||||||
|
if (!rep.hasFrequency() || (!rep.hasFrequencyMax() && rep.getFrequency() == 1) )
|
||||||
|
st = "Once";
|
||||||
|
else {
|
||||||
|
st = Integer.toString(rep.getFrequency());
|
||||||
|
if (rep.hasFrequencyMax())
|
||||||
|
st = st + "-"+Integer.toString(rep.getFrequency());
|
||||||
|
}
|
||||||
|
if (rep.hasPeriod()) {
|
||||||
|
st = st + " per "+rep.getPeriod().toPlainString();
|
||||||
|
if (rep.hasPeriodMax())
|
||||||
|
st = st + "-"+rep.getPeriodMax().toPlainString();
|
||||||
|
st = st + " "+displayTimeUnits(rep.getPeriodUnit());
|
||||||
|
}
|
||||||
|
b.append("Do "+st);
|
||||||
|
}
|
||||||
|
if (rep.hasBoundsPeriod() && rep.getBoundsPeriod().hasEnd())
|
||||||
|
b.append("Until "+rep.getBoundsPeriod().getEndElement().toHumanDisplay());
|
||||||
|
}
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayEventCode(EventTiming when) {
|
||||||
|
switch (when) {
|
||||||
|
case C: return "at meals";
|
||||||
|
case CD: return "at lunch";
|
||||||
|
case CM: return "at breakfast";
|
||||||
|
case CV: return "at dinner";
|
||||||
|
case AC: return "before meals";
|
||||||
|
case ACD: return "before lunch";
|
||||||
|
case ACM: return "before breakfast";
|
||||||
|
case ACV: return "before dinner";
|
||||||
|
case HS: return "before sleeping";
|
||||||
|
case PC: return "after meals";
|
||||||
|
case PCD: return "after lunch";
|
||||||
|
case PCM: return "after breakfast";
|
||||||
|
case PCV: return "after dinner";
|
||||||
|
case WAKE: return "after waking";
|
||||||
|
default: return "?ngen-6?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String displayTimeUnits(UnitsOfTime units) {
|
||||||
|
if (units == null)
|
||||||
|
return "?ngen-7?";
|
||||||
|
switch (units) {
|
||||||
|
case A: return "years";
|
||||||
|
case D: return "days";
|
||||||
|
case H: return "hours";
|
||||||
|
case MIN: return "minutes";
|
||||||
|
case MO: return "months";
|
||||||
|
case S: return "seconds";
|
||||||
|
case WK: return "weeks";
|
||||||
|
default: return "?ngen-8?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderTiming(XhtmlNode x, Timing s) throws FHIRException {
|
||||||
|
x.addText(displayTiming(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String displaySampledData(SampledData s) {
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
if (s.hasOrigin())
|
||||||
|
b.append("Origin: "+displayQuantity(s.getOrigin()));
|
||||||
|
|
||||||
|
if (s.hasPeriod())
|
||||||
|
b.append("Period: "+s.getPeriod().toString());
|
||||||
|
|
||||||
|
if (s.hasFactor())
|
||||||
|
b.append("Factor: "+s.getFactor().toString());
|
||||||
|
|
||||||
|
if (s.hasLowerLimit())
|
||||||
|
b.append("Lower: "+s.getLowerLimit().toString());
|
||||||
|
|
||||||
|
if (s.hasUpperLimit())
|
||||||
|
b.append("Upper: "+s.getUpperLimit().toString());
|
||||||
|
|
||||||
|
if (s.hasDimensions())
|
||||||
|
b.append("Dimensions: "+s.getDimensions());
|
||||||
|
|
||||||
|
if (s.hasData())
|
||||||
|
b.append("Data: "+s.getData());
|
||||||
|
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderSampledData(XhtmlNode x, SampledData sampledData) {
|
||||||
|
x.addText(displaySampledData(sampledData));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderingContext getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.model.Encounter;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class EncounterRenderer extends ResourceRenderer {
|
||||||
|
|
||||||
|
|
||||||
|
public EncounterRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(Encounter enc) {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, enc);
|
||||||
|
inject(enc, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, Encounter enc) {
|
||||||
|
describe(x, enc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, Encounter enc) {
|
||||||
|
x.tx(display(enc));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(Encounter enc) {
|
||||||
|
return "Not done yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.model.Patient;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class PatientRenderer extends ResourceRenderer {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PatientRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(Patient pat) {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, pat);
|
||||||
|
inject(pat, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, Patient pat) {
|
||||||
|
describe(x, pat);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, Patient pat) {
|
||||||
|
x.tx(display(pat));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(Patient pat) {
|
||||||
|
return "Not done yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.r5.model.Provenance;
|
||||||
|
import org.hl7.fhir.r5.model.Provenance;
|
||||||
|
import org.hl7.fhir.r5.model.Reference;
|
||||||
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.r5.model.Provenance.ProvenanceAgentComponent;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class ProvenanceRenderer extends ResourceRenderer {
|
||||||
|
|
||||||
|
public ProvenanceRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(Provenance prv) throws UnsupportedEncodingException, IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, prv);
|
||||||
|
inject(prv, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, Provenance prv) throws UnsupportedEncodingException, IOException {
|
||||||
|
boolean hasExtensions = false;
|
||||||
|
|
||||||
|
if (!prv.getTarget().isEmpty()) {
|
||||||
|
if (prv.getTarget().size() == 1) {
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.tx("Provenance for ");
|
||||||
|
renderReference(prv, p, prv.getTargetFirstRep());
|
||||||
|
} else {
|
||||||
|
x.para().tx("Provenance for:");
|
||||||
|
XhtmlNode ul = x.ul();
|
||||||
|
for (Reference ref : prv.getTarget()) {
|
||||||
|
renderReference(prv, ul.li(), ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// summary table
|
||||||
|
x.para().tx("Summary");
|
||||||
|
XhtmlNode t = x.table("grid");
|
||||||
|
XhtmlNode tr;
|
||||||
|
if (prv.hasOccurred()) {
|
||||||
|
tr = t.tr();
|
||||||
|
tr.td().tx("Occurrence");
|
||||||
|
if (prv.hasOccurredPeriod()) {
|
||||||
|
renderPeriod(tr.td(), prv.getOccurredPeriod());
|
||||||
|
} else {
|
||||||
|
renderDateTime(tr.td(), prv.getOccurredDateTimeType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prv.hasRecorded()) {
|
||||||
|
tr = t.tr();
|
||||||
|
tr.td().tx("Recorded");
|
||||||
|
tr.td().addText(prv.getRecordedElement().toHumanDisplay());
|
||||||
|
}
|
||||||
|
if (prv.hasPolicy()) {
|
||||||
|
tr = t.tr();
|
||||||
|
tr.td().tx("Policy");
|
||||||
|
if (prv.getPolicy().size() == 1) {
|
||||||
|
renderUri(tr.td(), prv.getPolicy().get(0));
|
||||||
|
} else {
|
||||||
|
XhtmlNode ul = tr.td().ul();
|
||||||
|
for (UriType u : prv.getPolicy()) {
|
||||||
|
renderUri(ul.li(), u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prv.hasLocation()) {
|
||||||
|
tr = t.tr();
|
||||||
|
tr.td().tx("Location");
|
||||||
|
renderReference(prv, tr.td(), prv.getLocation());
|
||||||
|
}
|
||||||
|
if (prv.hasActivity()) {
|
||||||
|
tr = t.tr();
|
||||||
|
tr.td().tx("Activity");
|
||||||
|
renderCodeableConcept(tr.td(), prv.getActivity(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasType = false;
|
||||||
|
boolean hasRole = false;
|
||||||
|
boolean hasOnBehalfOf = false;
|
||||||
|
for (ProvenanceAgentComponent a : prv.getAgent()) {
|
||||||
|
hasType = hasType || a.hasType();
|
||||||
|
hasRole = hasRole || a.hasRole();
|
||||||
|
hasOnBehalfOf = hasOnBehalfOf || a.hasOnBehalfOf();
|
||||||
|
}
|
||||||
|
x.para().tx("Agents");
|
||||||
|
t = x.table("grid");
|
||||||
|
tr = t.tr();
|
||||||
|
if (hasType) {
|
||||||
|
tr.td().b().tx("type");
|
||||||
|
}
|
||||||
|
if (hasRole) {
|
||||||
|
tr.td().b().tx("role");
|
||||||
|
}
|
||||||
|
tr.td().b().tx("who");
|
||||||
|
if (hasOnBehalfOf) {
|
||||||
|
tr.td().b().tx("onBehalfOf");
|
||||||
|
}
|
||||||
|
for (ProvenanceAgentComponent a : prv.getAgent()) {
|
||||||
|
tr = t.tr();
|
||||||
|
if (hasType) {
|
||||||
|
if (a.hasType()) {
|
||||||
|
renderCodeableConcept(tr.td(), a.getType(), false);
|
||||||
|
} else {
|
||||||
|
tr.td();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasRole) {
|
||||||
|
if (a.hasRole()) {
|
||||||
|
if (a.getRole().size() == 1) {
|
||||||
|
renderCodeableConcept(tr.td(), a.getType(), false);
|
||||||
|
} else {
|
||||||
|
XhtmlNode ul = tr.td().ul();
|
||||||
|
for (CodeableConcept cc : a.getRole()) {
|
||||||
|
renderCodeableConcept(ul.li(), cc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tr.td();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a.hasWho()) {
|
||||||
|
renderReference(prv, tr.td(), a.getWho());
|
||||||
|
} else {
|
||||||
|
tr.td();
|
||||||
|
}
|
||||||
|
if (hasOnBehalfOf) {
|
||||||
|
if (a.hasOnBehalfOf()) {
|
||||||
|
renderReference(prv, tr.td(), a.getOnBehalfOf());
|
||||||
|
} else {
|
||||||
|
tr.td();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// agent table
|
||||||
|
|
||||||
|
return hasExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, Provenance prv) throws UnsupportedEncodingException, IOException {
|
||||||
|
x.tx(display(prv));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(Provenance prv) throws UnsupportedEncodingException, IOException {
|
||||||
|
return "Provenance for "+displayReference(prv, prv.getTargetFirstRep());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,969 @@
|
||||||
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.formats.FormatUtilities;
|
||||||
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.r5.model.CodeType;
|
||||||
|
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
|
import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
|
import org.hl7.fhir.r5.model.ContactDetail;
|
||||||
|
import org.hl7.fhir.r5.model.ContactPoint;
|
||||||
|
import org.hl7.fhir.r5.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.r5.model.DomainResource;
|
||||||
|
import org.hl7.fhir.r5.model.Dosage;
|
||||||
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.Encounter;
|
||||||
|
import org.hl7.fhir.r5.model.Enumeration;
|
||||||
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
|
import org.hl7.fhir.r5.model.HumanName;
|
||||||
|
import org.hl7.fhir.r5.model.IdType;
|
||||||
|
import org.hl7.fhir.r5.model.Identifier;
|
||||||
|
import org.hl7.fhir.r5.model.InstantType;
|
||||||
|
import org.hl7.fhir.r5.model.Meta;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative;
|
||||||
|
import org.hl7.fhir.r5.model.Period;
|
||||||
|
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||||
|
import org.hl7.fhir.r5.model.Property;
|
||||||
|
import org.hl7.fhir.r5.model.Provenance;
|
||||||
|
import org.hl7.fhir.r5.model.Quantity;
|
||||||
|
import org.hl7.fhir.r5.model.Range;
|
||||||
|
import org.hl7.fhir.r5.model.Ratio;
|
||||||
|
import org.hl7.fhir.r5.model.Reference;
|
||||||
|
import org.hl7.fhir.r5.model.RelatedArtifact;
|
||||||
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
import org.hl7.fhir.r5.model.SampledData;
|
||||||
|
import org.hl7.fhir.r5.model.Signature;
|
||||||
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.Timing;
|
||||||
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
|
import org.hl7.fhir.r5.model.UsageContext;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.renderers.TerminologyRenderer.UsedConceptMap;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.DOMWrappers.BaseWrapperElement;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.DOMWrappers.ResourceWrapperElement;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.DirectWrappers.ResourceWrapperDirect;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.DirectWrappers.PropertyWrapperDirect;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.DirectWrappers.BaseWrapperDirect;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.ElementWrappers.ResourceWrapperMetaElement;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.IReferenceResolver;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
|
||||||
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
|
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||||
|
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
|
||||||
|
import org.hl7.fhir.r5.model.Address;
|
||||||
|
import org.hl7.fhir.r5.model.Annotation;
|
||||||
|
import org.hl7.fhir.r5.model.Attachment;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.Base64BinaryType;
|
||||||
|
import org.hl7.fhir.r5.model.BooleanType;
|
||||||
|
import org.hl7.fhir.r5.model.Bundle;
|
||||||
|
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
|
import org.hl7.fhir.r5.model.Patient;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
public class ResourceRenderer extends DataRenderer {
|
||||||
|
|
||||||
|
protected ResourceContext rcontext;
|
||||||
|
private XVerExtensionManager xverManager;
|
||||||
|
|
||||||
|
|
||||||
|
public ResourceRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||||
|
super(context);
|
||||||
|
this.rcontext = rcontext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* given a resource, update it's narrative with the best rendering available
|
||||||
|
*
|
||||||
|
* @param r - the domain resource in question
|
||||||
|
*
|
||||||
|
* @throws FHIRFormatError
|
||||||
|
* @throws DefinitionException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void render(DomainResource r) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
boolean hasExtensions = render(x, r);
|
||||||
|
inject(r, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean render(XhtmlNode x, DomainResource r) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
if (r instanceof CodeSystem) {
|
||||||
|
return new CodeSystemRenderer(context).render(x, (CodeSystem) r);
|
||||||
|
}
|
||||||
|
if (r instanceof ValueSet) {
|
||||||
|
return new ValueSetRenderer(context).render(x, (ValueSet) r);
|
||||||
|
}
|
||||||
|
if (r instanceof ConceptMap) {
|
||||||
|
return new ConceptMapRenderer(context).render(x, (ConceptMap) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Patient) {
|
||||||
|
return new PatientRenderer(context).render(x, (Patient) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Encounter) {
|
||||||
|
return new EncounterRenderer(context).render(x, (Encounter) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Provenance) {
|
||||||
|
return new ProvenanceRenderer(context).render(x, (Provenance) r);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, DomainResource r) throws UnsupportedEncodingException, IOException {
|
||||||
|
x.tx(display(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(DomainResource r) throws UnsupportedEncodingException, IOException {
|
||||||
|
if (r instanceof CodeSystem) {
|
||||||
|
return new CodeSystemRenderer(context).display((CodeSystem) r);
|
||||||
|
}
|
||||||
|
if (r instanceof ValueSet) {
|
||||||
|
return new ValueSetRenderer(context).display((ValueSet) r);
|
||||||
|
}
|
||||||
|
if (r instanceof ConceptMap) {
|
||||||
|
return new ConceptMapRenderer(context).display((ConceptMap) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Patient) {
|
||||||
|
return new PatientRenderer(context).display((Patient) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Encounter) {
|
||||||
|
return new EncounterRenderer(context).display((Encounter) r);
|
||||||
|
}
|
||||||
|
if (r instanceof Provenance) {
|
||||||
|
return new ProvenanceRenderer(context).display((Provenance) r);
|
||||||
|
}
|
||||||
|
return "todo";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void inject(DomainResource r, XhtmlNode x, NarrativeStatus status) {
|
||||||
|
if (!x.hasAttribute("xmlns"))
|
||||||
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
|
if (r.hasLanguage()) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", r.getLanguage());
|
||||||
|
x.setAttribute("xml:lang", r.getLanguage());
|
||||||
|
}
|
||||||
|
if (!r.hasText() || !r.getText().hasDiv() || r.getText().getDiv().getChildNodes().isEmpty()) {
|
||||||
|
r.setText(new Narrative());
|
||||||
|
r.getText().setDiv(x);
|
||||||
|
r.getText().setStatus(status);
|
||||||
|
} else {
|
||||||
|
XhtmlNode n = r.getText().getDiv();
|
||||||
|
n.hr();
|
||||||
|
n.getChildNodes().addAll(x.getChildNodes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inject(Element er, XhtmlNode x, NarrativeStatus status, boolean pretty) {
|
||||||
|
if (!x.hasAttribute("xmlns"))
|
||||||
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
|
Element le = XMLUtil.getNamedChild(er, "language");
|
||||||
|
String l = le == null ? null : le.getAttribute("value");
|
||||||
|
if (!Utilities.noString(l)) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", l);
|
||||||
|
x.setAttribute("xml:lang", l);
|
||||||
|
}
|
||||||
|
Element txt = XMLUtil.getNamedChild(er, "text");
|
||||||
|
if (txt == null) {
|
||||||
|
txt = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text");
|
||||||
|
Element n = XMLUtil.getFirstChild(er);
|
||||||
|
while (n != null && (n.getNodeName().equals("id") || n.getNodeName().equals("meta") || n.getNodeName().equals("implicitRules") || n.getNodeName().equals("language")))
|
||||||
|
n = XMLUtil.getNextSibling(n);
|
||||||
|
if (n == null)
|
||||||
|
er.appendChild(txt);
|
||||||
|
else
|
||||||
|
er.insertBefore(txt, n);
|
||||||
|
}
|
||||||
|
Element st = XMLUtil.getNamedChild(txt, "status");
|
||||||
|
if (st == null) {
|
||||||
|
st = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "status");
|
||||||
|
Element n = XMLUtil.getFirstChild(txt);
|
||||||
|
if (n == null)
|
||||||
|
txt.appendChild(st);
|
||||||
|
else
|
||||||
|
txt.insertBefore(st, n);
|
||||||
|
}
|
||||||
|
st.setAttribute("value", status.toCode());
|
||||||
|
Element div = XMLUtil.getNamedChild(txt, "div");
|
||||||
|
if (div == null) {
|
||||||
|
div = er.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "div");
|
||||||
|
div.setAttribute("xmlns", FormatUtilities.XHTML_NS);
|
||||||
|
txt.appendChild(div);
|
||||||
|
}
|
||||||
|
if (div.hasChildNodes())
|
||||||
|
div.appendChild(er.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "hr"));
|
||||||
|
new XhtmlComposer(XhtmlComposer.XML, pretty).compose(div, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inject(org.hl7.fhir.r5.elementmodel.Element er, XhtmlNode x, NarrativeStatus status, boolean pretty) throws IOException, FHIRException {
|
||||||
|
if (!x.hasAttribute("xmlns"))
|
||||||
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
|
String l = er.getChildValue("language");
|
||||||
|
if (!Utilities.noString(l)) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", l);
|
||||||
|
x.setAttribute("xml:lang", l);
|
||||||
|
}
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element txt = er.getNamedChild("text");
|
||||||
|
if (txt == null) {
|
||||||
|
txt = new org.hl7.fhir.r5.elementmodel.Element("text", er.getProperty().getChild(null, "text"));
|
||||||
|
int i = 0;
|
||||||
|
while (i < er.getChildren().size() && (er.getChildren().get(i).getName().equals("id") || er.getChildren().get(i).getName().equals("meta") || er.getChildren().get(i).getName().equals("implicitRules") || er.getChildren().get(i).getName().equals("language")))
|
||||||
|
i++;
|
||||||
|
if (i >= er.getChildren().size())
|
||||||
|
er.getChildren().add(txt);
|
||||||
|
else
|
||||||
|
er.getChildren().add(i, txt);
|
||||||
|
}
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element st = txt.getNamedChild("status");
|
||||||
|
if (st == null) {
|
||||||
|
st = new org.hl7.fhir.r5.elementmodel.Element("status", txt.getProperty().getChild(null, "status"));
|
||||||
|
txt.getChildren().add(0, st);
|
||||||
|
}
|
||||||
|
st.setValue(status.toCode());
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element div = txt.getNamedChild("div");
|
||||||
|
if (div == null) {
|
||||||
|
div = new org.hl7.fhir.r5.elementmodel.Element("div", txt.getProperty().getChild(null, "div"));
|
||||||
|
txt.getChildren().add(div);
|
||||||
|
div.setValue(new XhtmlComposer(XhtmlComposer.XML, pretty).compose(x));
|
||||||
|
}
|
||||||
|
div.setValue(x.toString());
|
||||||
|
div.setXhtml(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected void generateCopyright(XhtmlNode x, CanonicalResource cs) {
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Copyright Statement:", context.getLang()));
|
||||||
|
smartAddText(p, " " + cs.getCopyright());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String displayReference(Resource res, Reference r) throws UnsupportedEncodingException, IOException {
|
||||||
|
return "todo";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderReference(Resource res, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException {
|
||||||
|
ResourceWrapper rw = new ResourceWrapperDirect(this, res);
|
||||||
|
renderReference(rw, x, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderReference(ResourceWrapper rw, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException {
|
||||||
|
XhtmlNode c = x;
|
||||||
|
ResourceWithReference tr = null;
|
||||||
|
if (r.hasReferenceElement()) {
|
||||||
|
tr = resolveReference(rw, r.getReference());
|
||||||
|
|
||||||
|
if (!r.getReference().startsWith("#")) {
|
||||||
|
if (tr != null && tr.getReference() != null)
|
||||||
|
c = x.ah(tr.getReference());
|
||||||
|
else
|
||||||
|
c = x.ah(r.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// what to display: if text is provided, then that. if the reference was resolved, then show the generated narrative
|
||||||
|
if (r.hasDisplayElement()) {
|
||||||
|
c.addText(r.getDisplay());
|
||||||
|
if (tr != null && tr.getResource() != null) {
|
||||||
|
c.tx(". Generated Summary: ");
|
||||||
|
generateResourceSummary(c, tr.getResource(), true, r.getReference().startsWith("#"));
|
||||||
|
}
|
||||||
|
} else if (tr != null && tr.getResource() != null) {
|
||||||
|
generateResourceSummary(c, tr.getResource(), r.getReference().startsWith("#"), r.getReference().startsWith("#"));
|
||||||
|
} else {
|
||||||
|
c.addText(r.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResourceWithReference resolveReference(ResourceWrapper res, String url) {
|
||||||
|
if (url == null)
|
||||||
|
return null;
|
||||||
|
if (url.startsWith("#")) {
|
||||||
|
for (ResourceWrapper r : res.getContained()) {
|
||||||
|
if (r.getId().equals(url.substring(1)))
|
||||||
|
return new ResourceWithReference(null, r);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rcontext != null) {
|
||||||
|
BundleEntryComponent bundleResource = rcontext.resolve(url);
|
||||||
|
if (bundleResource != null) {
|
||||||
|
String bundleUrl = "#" + bundleResource.getResource().getResourceType().name().toLowerCase() + "_" + bundleResource.getResource().getId();
|
||||||
|
return new ResourceWithReference(bundleUrl, new ResourceWrapperDirect(this, bundleResource.getResource()));
|
||||||
|
}
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url);
|
||||||
|
if (bundleElement != null) {
|
||||||
|
String bundleUrl = null;
|
||||||
|
if (bundleElement.getNamedChild("resource").getChildValue("id") != null) {
|
||||||
|
bundleUrl = "#" + bundleElement.fhirType().toLowerCase() + "_" + bundleElement.getNamedChild("resource").getChildValue("id");
|
||||||
|
} else {
|
||||||
|
bundleUrl = "#" +fullUrlToAnchor(bundleElement.getChildValue("fullUrl"));
|
||||||
|
}
|
||||||
|
return new ResourceWithReference(bundleUrl, new ResourceWrapperMetaElement(this, bundleElement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource ae = getContext().getWorker().fetchResource(null, url);
|
||||||
|
if (ae != null)
|
||||||
|
return new ResourceWithReference(url, new ResourceWrapperDirect(this, ae));
|
||||||
|
else if (context.getResolver() != null) {
|
||||||
|
return context.getResolver().resolve(url);
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private String fullUrlToAnchor(String url) {
|
||||||
|
return url.replace(":", "").replace("/", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base parseType(String string, String type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateResourceSummary(XhtmlNode x, ResourceWrapper res, boolean textAlready, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
if (!textAlready) {
|
||||||
|
XhtmlNode div = res.getNarrative();
|
||||||
|
if (div != null) {
|
||||||
|
if (div.allChildrenAreText())
|
||||||
|
x.getChildNodes().addAll(div.getChildNodes());
|
||||||
|
if (div.getChildNodes().size() == 1 && div.getChildNodes().get(0).allChildrenAreText())
|
||||||
|
x.getChildNodes().addAll(div.getChildNodes().get(0).getChildNodes());
|
||||||
|
}
|
||||||
|
x.tx("Generated Summary: ");
|
||||||
|
}
|
||||||
|
String path = res.getName();
|
||||||
|
StructureDefinition profile = getContext().getWorker().fetchResource(StructureDefinition.class, path);
|
||||||
|
if (profile == null)
|
||||||
|
x.tx("unknown resource " +path);
|
||||||
|
else {
|
||||||
|
boolean firstElement = true;
|
||||||
|
boolean last = false;
|
||||||
|
for (PropertyWrapper p : res.children()) {
|
||||||
|
ElementDefinition child = getElementDefinition(profile.getSnapshot().getElement(), path+"."+p.getName(), p);
|
||||||
|
if (p.getValues().size() > 0 && p.getValues().get(0) != null && child != null && isPrimitive(child) && includeInSummary(child)) {
|
||||||
|
if (firstElement)
|
||||||
|
firstElement = false;
|
||||||
|
else if (last)
|
||||||
|
x.tx("; ");
|
||||||
|
boolean first = true;
|
||||||
|
last = false;
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else if (last)
|
||||||
|
x.tx(", ");
|
||||||
|
last = displayLeaf(res, v, child, x, p.getName(), showCodeDetails) || last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean includeInSummary(ElementDefinition child) {
|
||||||
|
if (child.getIsModifier())
|
||||||
|
return true;
|
||||||
|
if (child.getMustSupport())
|
||||||
|
return true;
|
||||||
|
if (child.getType().size() == 1) {
|
||||||
|
String t = child.getType().get(0).getWorkingCode();
|
||||||
|
if (t.equals("Address") || t.equals("Contact") || t.equals("Reference") || t.equals("Uri") || t.equals("Url") || t.equals("Canonical"))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ElementDefinition getElementDefinition(List<ElementDefinition> elements, String path, PropertyWrapper p) {
|
||||||
|
for (ElementDefinition element : elements)
|
||||||
|
if (element.getPath().equals(path))
|
||||||
|
return element;
|
||||||
|
if (path.endsWith("\"]") && p.getStructure() != null)
|
||||||
|
return p.getStructure().getSnapshot().getElement().get(0);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderLeaf(ResourceWrapper res, BaseWrapper ew, ElementDefinition defn, XhtmlNode x, boolean title, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
if (ew == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
Base e = ew.getBase();
|
||||||
|
|
||||||
|
if (e instanceof StringType)
|
||||||
|
x.addText(((StringType) e).getValue());
|
||||||
|
else if (e instanceof CodeType)
|
||||||
|
x.addText(((CodeType) e).getValue());
|
||||||
|
else if (e instanceof IdType)
|
||||||
|
x.addText(((IdType) e).getValue());
|
||||||
|
else if (e instanceof Extension)
|
||||||
|
return;
|
||||||
|
else if (e instanceof InstantType)
|
||||||
|
x.addText(((InstantType) e).toHumanDisplay());
|
||||||
|
else if (e instanceof DateTimeType) {
|
||||||
|
renderDateTime(x, e);
|
||||||
|
} else if (e instanceof Base64BinaryType)
|
||||||
|
x.addText(new Base64().encodeAsString(((Base64BinaryType) e).getValue()));
|
||||||
|
else if (e instanceof org.hl7.fhir.r5.model.DateType)
|
||||||
|
x.addText(((org.hl7.fhir.r5.model.DateType) e).toHumanDisplay());
|
||||||
|
else if (e instanceof Enumeration) {
|
||||||
|
Object ev = ((Enumeration<?>) e).getValue();
|
||||||
|
x.addText(ev == null ? "" : ev.toString()); // todo: look up a display name if there is one
|
||||||
|
} else if (e instanceof BooleanType)
|
||||||
|
x.addText(((BooleanType) e).getValue().toString());
|
||||||
|
else if (e instanceof CodeableConcept) {
|
||||||
|
renderCodeableConcept(x, (CodeableConcept) e, showCodeDetails);
|
||||||
|
} else if (e instanceof Coding) {
|
||||||
|
renderCoding(x, (Coding) e, showCodeDetails);
|
||||||
|
} else if (e instanceof Annotation) {
|
||||||
|
renderAnnotation(x, (Annotation) e);
|
||||||
|
} else if (e instanceof Identifier) {
|
||||||
|
renderIdentifier(x, (Identifier) e);
|
||||||
|
} else if (e instanceof org.hl7.fhir.r5.model.IntegerType) {
|
||||||
|
x.addText(Integer.toString(((org.hl7.fhir.r5.model.IntegerType) e).getValue()));
|
||||||
|
} else if (e instanceof org.hl7.fhir.r5.model.DecimalType) {
|
||||||
|
x.addText(((org.hl7.fhir.r5.model.DecimalType) e).getValue().toString());
|
||||||
|
} else if (e instanceof HumanName) {
|
||||||
|
renderHumanName(x, (HumanName) e);
|
||||||
|
} else if (e instanceof SampledData) {
|
||||||
|
renderSampledData(x, (SampledData) e);
|
||||||
|
} else if (e instanceof Address) {
|
||||||
|
renderAddress(x, (Address) e);
|
||||||
|
} else if (e instanceof ContactPoint) {
|
||||||
|
renderContactPoint(x, (ContactPoint) e);
|
||||||
|
} else if (e instanceof ContactDetail) {
|
||||||
|
ContactDetail cd = (ContactDetail) e;
|
||||||
|
if (cd.hasName()) {
|
||||||
|
x.tx(cd.getName()+": ");
|
||||||
|
}
|
||||||
|
boolean first = true;
|
||||||
|
for (ContactPoint c : cd.getTelecom()) {
|
||||||
|
if (first) first = false; else x.tx(",");
|
||||||
|
renderContactPoint(x, c);
|
||||||
|
}
|
||||||
|
} else if (e instanceof UriType) {
|
||||||
|
renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResourceResource() != null ? rcontext.getResourceResource().getId() : null);
|
||||||
|
} else if (e instanceof Timing) {
|
||||||
|
renderTiming(x, (Timing) e);
|
||||||
|
} else if (e instanceof Range) {
|
||||||
|
renderRange(x, (Range) e);
|
||||||
|
} else if (e instanceof Quantity) {
|
||||||
|
renderQuantity(x, (Quantity) e, showCodeDetails);
|
||||||
|
} else if (e instanceof Ratio) {
|
||||||
|
renderQuantity(x, ((Ratio) e).getNumerator(), showCodeDetails);
|
||||||
|
x.tx("/");
|
||||||
|
renderQuantity(x, ((Ratio) e).getDenominator(), showCodeDetails);
|
||||||
|
} else if (e instanceof Period) {
|
||||||
|
Period p = (Period) e;
|
||||||
|
renderPeriod(x, p);
|
||||||
|
} else if (e instanceof Reference) {
|
||||||
|
Reference r = (Reference) e;
|
||||||
|
renderReference(res, x, r);
|
||||||
|
} else if (e instanceof Resource) {
|
||||||
|
return;
|
||||||
|
} else if (e instanceof ElementDefinition) {
|
||||||
|
x.tx("todo-bundle");
|
||||||
|
} else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) {
|
||||||
|
StructureDefinition sd = getContext().getWorker().fetchTypeDefinition(e.fhirType());
|
||||||
|
if (sd == null)
|
||||||
|
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet, and no structure found");
|
||||||
|
else
|
||||||
|
generateByProfile(res, sd, ew, sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep(),
|
||||||
|
getChildrenForPath(sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep().getPath()), x, path, showCodeDetails, indent + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean displayLeaf(ResourceWrapper res, BaseWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
if (ew == null)
|
||||||
|
return false;
|
||||||
|
Base e = ew.getBase();
|
||||||
|
if (e == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Map<String, String> displayHints = readDisplayHints(defn);
|
||||||
|
|
||||||
|
if (name.endsWith("[x]"))
|
||||||
|
name = name.substring(0, name.length() - 3);
|
||||||
|
|
||||||
|
if (!showCodeDetails && e instanceof PrimitiveType && isDefault(displayHints, ((PrimitiveType) e)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (e instanceof StringType) {
|
||||||
|
x.addText(name+": "+((StringType) e).getValue());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof CodeType) {
|
||||||
|
x.addText(name+": "+((CodeType) e).getValue());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof IdType) {
|
||||||
|
x.addText(name+": "+((IdType) e).getValue());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof UriType) {
|
||||||
|
x.addText(name+": "+((UriType) e).getValue());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof DateTimeType) {
|
||||||
|
x.addText(name+": "+((DateTimeType) e).toHumanDisplay());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof InstantType) {
|
||||||
|
x.addText(name+": "+((InstantType) e).toHumanDisplay());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Extension) {
|
||||||
|
// x.tx("Extensions: todo");
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof org.hl7.fhir.r5.model.DateType) {
|
||||||
|
x.addText(name+": "+((org.hl7.fhir.r5.model.DateType) e).toHumanDisplay());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Enumeration) {
|
||||||
|
x.addText(((Enumeration<?>) e).getValue().toString()); // todo: look up a display name if there is one
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof BooleanType) {
|
||||||
|
if (((BooleanType) e).getValue()) {
|
||||||
|
x.addText(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (e instanceof CodeableConcept) {
|
||||||
|
renderCodeableConcept(x, (CodeableConcept) e, showCodeDetails);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Coding) {
|
||||||
|
renderCoding(x, (Coding) e, showCodeDetails);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Annotation) {
|
||||||
|
renderAnnotation(x, (Annotation) e, showCodeDetails);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof org.hl7.fhir.r5.model.IntegerType) {
|
||||||
|
x.addText(Integer.toString(((org.hl7.fhir.r5.model.IntegerType) e).getValue()));
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof org.hl7.fhir.r5.model.DecimalType) {
|
||||||
|
x.addText(((org.hl7.fhir.r5.model.DecimalType) e).getValue().toString());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Identifier) {
|
||||||
|
renderIdentifier(x, (Identifier) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof HumanName) {
|
||||||
|
renderHumanName(x, (HumanName) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof SampledData) {
|
||||||
|
renderSampledData(x, (SampledData) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Address) {
|
||||||
|
renderAddress(x, (Address) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof ContactPoint) {
|
||||||
|
renderContactPoint(x, (ContactPoint) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Timing) {
|
||||||
|
renderTiming(x, (Timing) e);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Quantity) {
|
||||||
|
renderQuantity(x, (Quantity) e, showCodeDetails);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Ratio) {
|
||||||
|
renderQuantity(x, ((Ratio) e).getNumerator(), showCodeDetails);
|
||||||
|
x.tx("/");
|
||||||
|
renderQuantity(x, ((Ratio) e).getDenominator(), showCodeDetails);
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Period) {
|
||||||
|
Period p = (Period) e;
|
||||||
|
x.addText(name+": ");
|
||||||
|
x.addText(!p.hasStart() ? "?ngen-2?" : p.getStartElement().toHumanDisplay());
|
||||||
|
x.tx(" --> ");
|
||||||
|
x.addText(!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay());
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Reference) {
|
||||||
|
Reference r = (Reference) e;
|
||||||
|
if (r.hasDisplayElement())
|
||||||
|
x.addText(r.getDisplay());
|
||||||
|
else if (r.hasReferenceElement()) {
|
||||||
|
ResourceWithReference tr = resolveReference(res, r.getReference());
|
||||||
|
x.addText(tr == null ? r.getReference() : "?ngen-3"); // getDisplayForReference(tr.getReference()));
|
||||||
|
} else
|
||||||
|
x.tx("?ngen-4?");
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Narrative) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof Resource) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof ContactDetail) {
|
||||||
|
ContactDetail cd = (ContactDetail) e;
|
||||||
|
if (cd.hasName()) {
|
||||||
|
x.tx(cd.getName()+": ");
|
||||||
|
}
|
||||||
|
boolean first = true;
|
||||||
|
for (ContactPoint c : cd.getTelecom()) {
|
||||||
|
if (first) first = false; else x.tx(",");
|
||||||
|
renderContactPoint(x, c);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (e instanceof Range) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof Meta) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof Dosage) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof Signature) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof UsageContext) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof RelatedArtifact) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof ElementDefinition) {
|
||||||
|
return false;
|
||||||
|
} else if (e instanceof Base64BinaryType) {
|
||||||
|
return false;
|
||||||
|
} else if (!(e instanceof Attachment))
|
||||||
|
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isPrimitive(ElementDefinition e) {
|
||||||
|
//we can tell if e is a primitive because it has types
|
||||||
|
if (e.getType().isEmpty())
|
||||||
|
return false;
|
||||||
|
if (e.getType().size() == 1 && isBase(e.getType().get(0).getWorkingCode()))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
// return !e.getType().isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBase(String code) {
|
||||||
|
return code.equals("Element") || code.equals("BackboneElement");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ElementDefinition> getChildrenForPath(List<ElementDefinition> elements, String path) throws DefinitionException {
|
||||||
|
// do we need to do a name reference substitution?
|
||||||
|
for (ElementDefinition e : elements) {
|
||||||
|
if (e.getPath().equals(path) && e.hasContentReference()) {
|
||||||
|
String ref = e.getContentReference();
|
||||||
|
ElementDefinition t = null;
|
||||||
|
// now, resolve the name
|
||||||
|
for (ElementDefinition e1 : elements) {
|
||||||
|
if (ref.equals("#"+e1.getId()))
|
||||||
|
t = e1;
|
||||||
|
}
|
||||||
|
if (t == null)
|
||||||
|
throw new DefinitionException("Unable to resolve content reference "+ref+" trying to resolve "+path);
|
||||||
|
path = t.getPath();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ElementDefinition> results = new ArrayList<ElementDefinition>();
|
||||||
|
for (ElementDefinition e : elements) {
|
||||||
|
if (e.getPath().startsWith(path+".") && !e.getPath().substring(path.length()+1).contains("."))
|
||||||
|
results.add(e);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean generateByProfile(StructureDefinition profile, boolean showCodeDetails) {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
x.para().b().tx("Generated Narrative"+(showCodeDetails ? " with Details" : ""));
|
||||||
|
try {
|
||||||
|
generateByProfile(rcontext.getResourceResource(), profile, rcontext.getResourceResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), rcontext.getResourceResource().getResourceType().toString()), x, rcontext.getResourceResource().getResourceType().toString(), showCodeDetails);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||||
|
}
|
||||||
|
inject(rcontext.getResourceResource(), x, NarrativeStatus.GENERATED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateByProfile(Element er, StructureDefinition profile, boolean showCodeDetails) throws IOException, org.hl7.fhir.exceptions.FHIRException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
x.para().b().tx("Generated Narrative"+(showCodeDetails ? " with Details" : ""));
|
||||||
|
try {
|
||||||
|
generateByProfile(er, profile, er, profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), er.getLocalName()), x, er.getLocalName(), showCodeDetails);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||||
|
}
|
||||||
|
inject(er, x, NarrativeStatus.GENERATED, false);
|
||||||
|
String b = new XhtmlComposer(XhtmlComposer.XML, false).compose(x);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateByProfile(Element eres, StructureDefinition profile, Element ee, List<ElementDefinition> allElements, ElementDefinition defn, List<ElementDefinition> children, XhtmlNode x, String path, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
|
||||||
|
ResourceWrapperElement resw = new ResourceWrapperElement(this, eres, profile);
|
||||||
|
BaseWrapperElement base = new BaseWrapperElement(this, ee, null, profile, profile.getSnapshot().getElement().get(0));
|
||||||
|
generateByProfile(resw, profile, base, allElements, defn, children, x, path, showCodeDetails, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void generateByProfile(Resource res, StructureDefinition profile, Base e, List<ElementDefinition> allElements, ElementDefinition defn, List<ElementDefinition> children, XhtmlNode x, String path, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
generateByProfile(new ResourceWrapperDirect(this, res), profile, new BaseWrapperDirect(this, e), allElements, defn, children, x, path, showCodeDetails, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateByProfile(ResourceWrapper res, StructureDefinition profile, BaseWrapper e, List<ElementDefinition> allElements, ElementDefinition defn, List<ElementDefinition> children, XhtmlNode x, String path, boolean showCodeDetails, int indent) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
if (children.isEmpty()) {
|
||||||
|
renderLeaf(res, e, defn, x, false, showCodeDetails, readDisplayHints(defn), path, indent);
|
||||||
|
} else {
|
||||||
|
for (PropertyWrapper p : splitExtensions(profile, e.children())) {
|
||||||
|
if (p.hasValues()) {
|
||||||
|
ElementDefinition child = getElementDefinition(children, path+"."+p.getName(), p);
|
||||||
|
if (child != null) {
|
||||||
|
Map<String, String> displayHints = readDisplayHints(child);
|
||||||
|
if (!exemptFromRendering(child)) {
|
||||||
|
List<ElementDefinition> grandChildren = getChildrenForPath(allElements, path+"."+p.getName());
|
||||||
|
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
||||||
|
if (p.getValues().size() > 0 && child != null) {
|
||||||
|
if (isPrimitive(child)) {
|
||||||
|
XhtmlNode para = x.para();
|
||||||
|
String name = p.getName();
|
||||||
|
if (name.endsWith("[x]"))
|
||||||
|
name = name.substring(0, name.length() - 3);
|
||||||
|
if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) {
|
||||||
|
para.b().addText(name);
|
||||||
|
para.tx(": ");
|
||||||
|
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||||
|
XhtmlNode list = x.ul();
|
||||||
|
for (BaseWrapper v : p.getValues())
|
||||||
|
renderLeaf(res, v, child, list.li(), false, showCodeDetails, displayHints, path, indent);
|
||||||
|
} else {
|
||||||
|
boolean first = true;
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
para.tx(", ");
|
||||||
|
renderLeaf(res, v, child, para, false, showCodeDetails, displayHints, path, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (canDoTable(path, p, grandChildren)) {
|
||||||
|
x.addTag(getHeader()).addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||||
|
XhtmlNode tbl = x.table( "grid");
|
||||||
|
XhtmlNode tr = tbl.tr();
|
||||||
|
tr.td().tx("-"); // work around problem with empty table rows
|
||||||
|
addColumnHeadings(tr, grandChildren);
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
if (v != null) {
|
||||||
|
tr = tbl.tr();
|
||||||
|
tr.td().tx("*"); // work around problem with empty table rows
|
||||||
|
addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
if (v != null) {
|
||||||
|
XhtmlNode bq = x.addTag("blockquote");
|
||||||
|
bq.para().b().addText(p.getName());
|
||||||
|
generateByProfile(res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getHeader() {
|
||||||
|
int i = 3;
|
||||||
|
while (i <= context.getHeaderLevelContext())
|
||||||
|
i++;
|
||||||
|
if (i > 6)
|
||||||
|
i = 6;
|
||||||
|
return "h"+Integer.toString(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PropertyWrapper> getValues(String path, PropertyWrapper p, ElementDefinition e) {
|
||||||
|
List<PropertyWrapper> res = new ArrayList<PropertyWrapper>();
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
for (PropertyWrapper g : v.children()) {
|
||||||
|
if ((path+"."+p.getName()+"."+g.getName()).equals(e.getPath()))
|
||||||
|
res.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDoTable(String path, PropertyWrapper p, List<ElementDefinition> grandChildren) {
|
||||||
|
for (ElementDefinition e : grandChildren) {
|
||||||
|
List<PropertyWrapper> values = getValues(path, p, e);
|
||||||
|
if (values.size() > 1 || !isPrimitive(e) || !canCollapse(e))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean canCollapse(ElementDefinition e) {
|
||||||
|
// we can collapse any data type
|
||||||
|
return !e.getType().isEmpty();
|
||||||
|
}
|
||||||
|
private boolean exemptFromRendering(ElementDefinition child) {
|
||||||
|
if (child == null)
|
||||||
|
return false;
|
||||||
|
if ("Composition.subject".equals(child.getPath()))
|
||||||
|
return true;
|
||||||
|
if ("Composition.section".equals(child.getPath()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean renderAsList(ElementDefinition child) {
|
||||||
|
if (child.getType().size() == 1) {
|
||||||
|
String t = child.getType().get(0).getWorkingCode();
|
||||||
|
if (t.equals("Address") || t.equals("Reference"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addColumnHeadings(XhtmlNode tr, List<ElementDefinition> grandChildren) {
|
||||||
|
for (ElementDefinition e : grandChildren)
|
||||||
|
tr.td().b().addText(Utilities.capitalize(tail(e.getPath())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addColumnValues(ResourceWrapper res, XhtmlNode tr, List<ElementDefinition> grandChildren, BaseWrapper v, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
|
for (ElementDefinition e : grandChildren) {
|
||||||
|
PropertyWrapper p = v.getChildByName(e.getPath().substring(e.getPath().lastIndexOf(".")+1));
|
||||||
|
if (p == null || p.getValues().size() == 0 || p.getValues().get(0) == null)
|
||||||
|
tr.td().tx(" ");
|
||||||
|
else
|
||||||
|
renderLeaf(res, p.getValues().get(0), e, tr.td(), false, showCodeDetails, displayHints, path, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterGrandChildren(List<ElementDefinition> grandChildren, String string, PropertyWrapper prop) {
|
||||||
|
List<ElementDefinition> toRemove = new ArrayList<ElementDefinition>();
|
||||||
|
toRemove.addAll(grandChildren);
|
||||||
|
for (BaseWrapper b : prop.getValues()) {
|
||||||
|
List<ElementDefinition> list = new ArrayList<ElementDefinition>();
|
||||||
|
for (ElementDefinition ed : toRemove) {
|
||||||
|
PropertyWrapper p = b.getChildByName(tail(ed.getPath()));
|
||||||
|
if (p != null && p.hasValues())
|
||||||
|
list.add(ed);
|
||||||
|
}
|
||||||
|
toRemove.removeAll(list);
|
||||||
|
}
|
||||||
|
grandChildren.removeAll(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PropertyWrapper> splitExtensions(StructureDefinition profile, List<PropertyWrapper> children) throws UnsupportedEncodingException, IOException, FHIRException {
|
||||||
|
List<PropertyWrapper> results = new ArrayList<PropertyWrapper>();
|
||||||
|
Map<String, PropertyWrapper> map = new HashMap<String, PropertyWrapper>();
|
||||||
|
for (PropertyWrapper p : children)
|
||||||
|
if (p.getName().equals("extension") || p.getName().equals("modifierExtension")) {
|
||||||
|
// we're going to split these up, and create a property for each url
|
||||||
|
if (p.hasValues()) {
|
||||||
|
for (BaseWrapper v : p.getValues()) {
|
||||||
|
Extension ex = (Extension) v.getBase();
|
||||||
|
String url = ex.getUrl();
|
||||||
|
StructureDefinition ed = getContext().getWorker().fetchResource(StructureDefinition.class, url);
|
||||||
|
if (ed == null) {
|
||||||
|
if (xverManager == null) {
|
||||||
|
xverManager = new XVerExtensionManager(context.getWorker());
|
||||||
|
}
|
||||||
|
if (xverManager.matchingUrl(url) && xverManager.status(url) == XVerExtensionStatus.Valid) {
|
||||||
|
ed = xverManager.makeDefinition(url);
|
||||||
|
getContext().getWorker().generateSnapshot(ed);
|
||||||
|
getContext().getWorker().cacheResource(ed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.getName().equals("modifierExtension") && ed == null)
|
||||||
|
throw new DefinitionException("Unknown modifier extension "+url);
|
||||||
|
PropertyWrapper pe = map.get(p.getName()+"["+url+"]");
|
||||||
|
if (pe == null) {
|
||||||
|
if (ed == null) {
|
||||||
|
if (url.startsWith("http://hl7.org/fhir") && !url.startsWith("http://hl7.org/fhir/us"))
|
||||||
|
throw new DefinitionException("unknown extension "+url);
|
||||||
|
// System.out.println("unknown extension "+url);
|
||||||
|
pe = new PropertyWrapperDirect(this, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex));
|
||||||
|
} else {
|
||||||
|
ElementDefinition def = ed.getSnapshot().getElement().get(0);
|
||||||
|
pe = new PropertyWrapperDirect(this, new Property(p.getName()+"["+url+"]", "Extension", def.getDefinition(), def.getMin(), def.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(def.getMax()), ex));
|
||||||
|
((PropertyWrapperDirect) pe).getWrapped().setStructure(ed);
|
||||||
|
}
|
||||||
|
results.add(pe);
|
||||||
|
} else
|
||||||
|
pe.getValues().add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
results.add(p);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, String> readDisplayHints(ElementDefinition defn) throws DefinitionException {
|
||||||
|
Map<String, String> hints = new HashMap<String, String>();
|
||||||
|
if (defn != null) {
|
||||||
|
String displayHint = ToolingExtensions.getDisplayHint(defn);
|
||||||
|
if (!Utilities.noString(displayHint)) {
|
||||||
|
String[] list = displayHint.split(";");
|
||||||
|
for (String item : list) {
|
||||||
|
String[] parts = item.split(":");
|
||||||
|
if (parts.length != 2)
|
||||||
|
throw new DefinitionException("error reading display hint: '"+displayHint+"'");
|
||||||
|
hints.put(parts[0].trim(), parts[1].trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private boolean isDefaultValue(Map<String, String> displayHints, List<BaseWrapper> list) throws UnsupportedEncodingException, IOException, FHIRException {
|
||||||
|
if (list.size() != 1)
|
||||||
|
return false;
|
||||||
|
if (list.get(0).getBase() instanceof PrimitiveType)
|
||||||
|
return isDefault(displayHints, (PrimitiveType) list.get(0).getBase());
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDefault(Map<String, String> displayHints, PrimitiveType primitiveType) {
|
||||||
|
String v = primitiveType.asStringValue();
|
||||||
|
if (!Utilities.noString(v) && displayHints.containsKey("default") && v.equals(displayHints.get("default")))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String tail(String path) {
|
||||||
|
return path.substring(path.lastIndexOf(".")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hl7.fhir.r5.terminologies;
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -7,8 +7,6 @@ import java.util.List;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
|
||||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.ConceptMap;
|
import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
|
@ -17,6 +15,7 @@ import org.hl7.fhir.r5.model.Questionnaire;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
||||||
|
@ -29,20 +28,25 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.r5.utils.NarrativeGenerator.ResourceContext;
|
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
|
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
|
||||||
|
|
||||||
public class TerminologyRenderer {
|
public class TerminologyRenderer extends ResourceRenderer {
|
||||||
|
|
||||||
public enum TerminologyRendererMode {
|
public TerminologyRenderer(RenderingContext context) {
|
||||||
RESOURCE, IG
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminologyRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||||
|
super(context, rcontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class TargetElementComponentWrapper {
|
protected class TargetElementComponentWrapper {
|
||||||
|
@ -100,53 +104,8 @@ public class TerminologyRenderer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TerminologyRendererMode mode;
|
|
||||||
protected IWorkerContext context;
|
|
||||||
protected MarkDownProcessor markdown;
|
|
||||||
protected String lang;
|
|
||||||
protected String prefix;
|
|
||||||
protected int headerLevelContext;
|
|
||||||
protected ValidationOptions terminologyServiceOptions = new ValidationOptions();
|
|
||||||
protected boolean noSlowLookup;
|
protected boolean noSlowLookup;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param mode - whether we are rendering for a resource directly, or for an IG
|
|
||||||
* @param context - common services (terminology server, code system cache etc)
|
|
||||||
* @param markdown - markdown processing engine of the correct sort for the version applicable
|
|
||||||
* @param prefix - the path to the base FHIR specification
|
|
||||||
* @param lang - the language to use (null for the default)
|
|
||||||
*/
|
|
||||||
public TerminologyRenderer(TerminologyRendererMode mode, IWorkerContext context, MarkDownProcessor markdown, String prefix, String lang) {
|
|
||||||
super();
|
|
||||||
this.mode = mode;
|
|
||||||
this.context = context;
|
|
||||||
this.markdown = markdown;
|
|
||||||
this.lang = lang;
|
|
||||||
this.prefix = prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TerminologyRendererMode getMode() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeaderLevelContext() {
|
|
||||||
return headerLevelContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaderLevelContext(int headerLevelContext) {
|
|
||||||
this.headerLevelContext = headerLevelContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValidationOptions getTerminologyServiceOptions() {
|
|
||||||
return terminologyServiceOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTerminologyServiceOptions(ValidationOptions terminologyServiceOptions) {
|
|
||||||
this.terminologyServiceOptions = terminologyServiceOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isNoSlowLookup() {
|
public boolean isNoSlowLookup() {
|
||||||
return noSlowLookup;
|
return noSlowLookup;
|
||||||
|
@ -156,66 +115,11 @@ public class TerminologyRenderer {
|
||||||
this.noSlowLookup = noSlowLookup;
|
this.noSlowLookup = noSlowLookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addMarkdown(XhtmlNode x, String text) throws FHIRFormatError, IOException, DefinitionException {
|
|
||||||
if (text != null) {
|
|
||||||
// 1. custom FHIR extensions
|
|
||||||
while (text.contains("[[[")) {
|
|
||||||
String left = text.substring(0, text.indexOf("[[["));
|
|
||||||
String link = text.substring(text.indexOf("[[[")+3, text.indexOf("]]]"));
|
|
||||||
String right = text.substring(text.indexOf("]]]")+3);
|
|
||||||
String url = link;
|
|
||||||
String[] parts = link.split("\\#");
|
|
||||||
StructureDefinition p = context.fetchResource(StructureDefinition.class, parts[0]);
|
|
||||||
if (p == null)
|
|
||||||
p = context.fetchTypeDefinition(parts[0]);
|
|
||||||
if (p == null)
|
|
||||||
p = context.fetchResource(StructureDefinition.class, link);
|
|
||||||
if (p != null) {
|
|
||||||
url = p.getUserString("path");
|
|
||||||
if (url == null)
|
|
||||||
url = p.getUserString("filename");
|
|
||||||
} else
|
|
||||||
throw new DefinitionException("Unable to resolve markdown link "+link);
|
|
||||||
|
|
||||||
text = left+"["+link+"]("+url+")"+right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. markdown
|
|
||||||
String s = markdown.process(Utilities.escapeXml(text), "narrative generator");
|
|
||||||
XhtmlParser p = new XhtmlParser();
|
|
||||||
XhtmlNode m;
|
|
||||||
try {
|
|
||||||
m = p.parse("<div>"+s+"</div>", "div");
|
|
||||||
} catch (org.hl7.fhir.exceptions.FHIRFormatError e) {
|
|
||||||
throw new FHIRFormatError(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
x.getChildNodes().addAll(m.getChildNodes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void generateCopyright(XhtmlNode x, CanonicalResource cs) {
|
|
||||||
XhtmlNode p = x.para();
|
|
||||||
p.b().tx(context.translator().translate("xhtml-gen-cs", "Copyright Statement:", lang));
|
|
||||||
smartAddText(p, " " + cs.getCopyright());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void smartAddText(XhtmlNode p, String text) {
|
|
||||||
if (text == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
String[] lines = text.split("\\r\\n");
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
|
||||||
if (i > 0)
|
|
||||||
p.br();
|
|
||||||
p.addText(lines[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addMapHeaders(XhtmlNode tr, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
protected void addMapHeaders(XhtmlNode tr, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
for (UsedConceptMap m : maps) {
|
for (UsedConceptMap m : maps) {
|
||||||
XhtmlNode td = tr.td();
|
XhtmlNode td = tr.td();
|
||||||
XhtmlNode b = td.b();
|
XhtmlNode b = td.b();
|
||||||
XhtmlNode a = b.ah(prefix+m.getLink());
|
XhtmlNode a = b.ah(getContext().getPrefix()+m.getLink());
|
||||||
a.addText(m.getDetails().getName());
|
a.addText(m.getDetails().getName());
|
||||||
if (m.getDetails().isDoDescription() && m.getMap().hasDescription())
|
if (m.getDetails().isDoDescription() && m.getMap().hasDescription())
|
||||||
addMarkdown(td, m.getMap().getDescription());
|
addMarkdown(td, m.getMap().getDescription());
|
||||||
|
@ -224,45 +128,13 @@ public class TerminologyRenderer {
|
||||||
|
|
||||||
protected String getHeader() {
|
protected String getHeader() {
|
||||||
int i = 3;
|
int i = 3;
|
||||||
while (i <= headerLevelContext)
|
while (i <= getContext().getHeaderLevelContext())
|
||||||
i++;
|
i++;
|
||||||
if (i > 6)
|
if (i > 6)
|
||||||
i = 6;
|
i = 6;
|
||||||
return "h"+Integer.toString(i);
|
return "h"+Integer.toString(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String describeSystem(String system) {
|
|
||||||
if (system == null)
|
|
||||||
return "[not stated]";
|
|
||||||
if (system.equals("http://loinc.org"))
|
|
||||||
return "LOINC";
|
|
||||||
if (system.startsWith("http://snomed.info"))
|
|
||||||
return "SNOMED CT";
|
|
||||||
if (system.equals("http://www.nlm.nih.gov/research/umls/rxnorm"))
|
|
||||||
return "RxNorm";
|
|
||||||
if (system.equals("http://hl7.org/fhir/sid/icd-9"))
|
|
||||||
return "ICD-9";
|
|
||||||
if (system.equals("http://dicom.nema.org/resources/ontology/DCM"))
|
|
||||||
return "DICOM";
|
|
||||||
if (system.equals("http://unitsofmeasure.org"))
|
|
||||||
return "UCUM";
|
|
||||||
|
|
||||||
return system;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected String makeAnchor(String codeSystem, String code) {
|
|
||||||
String s = codeSystem+'-'+code;
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
for (char c : s.toCharArray()) {
|
|
||||||
if (Character.isAlphabetic(c) || Character.isDigit(c) || c == '.')
|
|
||||||
b.append(c);
|
|
||||||
else
|
|
||||||
b.append('-');
|
|
||||||
}
|
|
||||||
return b.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<TargetElementComponentWrapper> findMappingsForCode(String code, ConceptMap map) {
|
protected List<TargetElementComponentWrapper> findMappingsForCode(String code, ConceptMap map) {
|
||||||
List<TargetElementComponentWrapper> mappings = new ArrayList<TargetElementComponentWrapper>();
|
List<TargetElementComponentWrapper> mappings = new ArrayList<TargetElementComponentWrapper>();
|
||||||
|
|
||||||
|
@ -307,11 +179,11 @@ public class TerminologyRenderer {
|
||||||
XhtmlNode a = li.ah(spec);
|
XhtmlNode a = li.ah(spec);
|
||||||
a.code(inc.getSystem());
|
a.code(inc.getSystem());
|
||||||
} else if (cs != null && ref != null) {
|
} else if (cs != null && ref != null) {
|
||||||
if (!Utilities.noString(prefix) && ref.startsWith("http://hl7.org/fhir/"))
|
if (!Utilities.noString(getContext().getPrefix()) && ref.startsWith("http://hl7.org/fhir/"))
|
||||||
ref = ref.substring(20)+"/index.html";
|
ref = ref.substring(20)+"/index.html";
|
||||||
else if (addHtml && !ref.contains(".html"))
|
else if (addHtml && !ref.contains(".html"))
|
||||||
ref = ref + ".html";
|
ref = ref + ".html";
|
||||||
XhtmlNode a = li.ah(prefix+ref.replace("\\", "/"));
|
XhtmlNode a = li.ah(getContext().getPrefix()+ref.replace("\\", "/"));
|
||||||
a.code(inc.getSystem());
|
a.code(inc.getSystem());
|
||||||
} else {
|
} else {
|
||||||
li.code(inc.getSystem());
|
li.code(inc.getSystem());
|
||||||
|
@ -335,17 +207,17 @@ public class TerminologyRenderer {
|
||||||
XhtmlNode tr = t.tr();
|
XhtmlNode tr = t.tr();
|
||||||
if (hasHierarchy)
|
if (hasHierarchy)
|
||||||
tr.td().b().tx("Lvl");
|
tr.td().b().tx("Lvl");
|
||||||
tr.td().attribute("style", "white-space:nowrap").b().tx(context.translator().translate("xhtml-gen-cs", "Code", lang));
|
tr.td().attribute("style", "white-space:nowrap").b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Code", getContext().getLang()));
|
||||||
if (hasDisplay)
|
if (hasDisplay)
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Display", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Display", getContext().getLang()));
|
||||||
if (definitions)
|
if (definitions)
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Definition", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Definition", getContext().getLang()));
|
||||||
if (deprecated)
|
if (deprecated)
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Deprecated", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Deprecated", getContext().getLang()));
|
||||||
if (comments)
|
if (comments)
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Comments", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Comments", getContext().getLang()));
|
||||||
if (version)
|
if (version)
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", "Version", lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Version", getContext().getLang()));
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
for (PropertyComponent pc : properties) {
|
for (PropertyComponent pc : properties) {
|
||||||
String display = ToolingExtensions.getPresentation(pc, pc.getCodeElement());
|
String display = ToolingExtensions.getPresentation(pc, pc.getCodeElement());
|
||||||
|
@ -355,7 +227,7 @@ public class TerminologyRenderer {
|
||||||
display = pc.getCode();
|
display = pc.getCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tr.td().b().tx(context.translator().translate("xhtml-gen-cs", display, lang));
|
tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", display, getContext().getLang()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tr;
|
return tr;
|
||||||
|
@ -371,7 +243,7 @@ public class TerminologyRenderer {
|
||||||
code = uri.substring(uri.indexOf("#")+1);
|
code = uri.substring(uri.indexOf("#")+1);
|
||||||
uri = uri.substring(0, uri.indexOf("#"));
|
uri = uri.substring(0, uri.indexOf("#"));
|
||||||
}
|
}
|
||||||
CodeSystem cs = context.fetchCodeSystem(uri);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(uri);
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +252,7 @@ public class TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void AddVsRef(ResourceContext rcontext, String value, XhtmlNode li) {
|
protected void AddVsRef(String value, XhtmlNode li) {
|
||||||
Resource res = null;
|
Resource res = null;
|
||||||
if (rcontext != null) {
|
if (rcontext != null) {
|
||||||
BundleEntryComponent be = rcontext.resolve(value);
|
BundleEntryComponent be = rcontext.resolve(value);
|
||||||
|
@ -394,13 +266,13 @@ public class TerminologyRenderer {
|
||||||
}
|
}
|
||||||
CanonicalResource vs = (CanonicalResource) res;
|
CanonicalResource vs = (CanonicalResource) res;
|
||||||
if (vs == null)
|
if (vs == null)
|
||||||
vs = context.fetchResource(ValueSet.class, value);
|
vs = getContext().getWorker().fetchResource(ValueSet.class, value);
|
||||||
if (vs == null)
|
if (vs == null)
|
||||||
vs = context.fetchResource(StructureDefinition.class, value);
|
vs = getContext().getWorker().fetchResource(StructureDefinition.class, value);
|
||||||
// if (vs == null)
|
// if (vs == null)
|
||||||
// vs = context.fetchResource(DataElement.class, value);
|
// vs = context.getWorker().fetchResource(DataElement.class, value);
|
||||||
if (vs == null)
|
if (vs == null)
|
||||||
vs = context.fetchResource(Questionnaire.class, value);
|
vs = getContext().getWorker().fetchResource(Questionnaire.class, value);
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
String ref = (String) vs.getUserData("path");
|
String ref = (String) vs.getUserData("path");
|
||||||
|
|
||||||
|
@ -408,7 +280,7 @@ public class TerminologyRenderer {
|
||||||
XhtmlNode a = li.ah(ref == null ? "?ngen-11?" : ref.replace("\\", "/"));
|
XhtmlNode a = li.ah(ref == null ? "?ngen-11?" : ref.replace("\\", "/"));
|
||||||
a.addText(value);
|
a.addText(value);
|
||||||
} else {
|
} else {
|
||||||
CodeSystem cs = context.fetchCodeSystem(value);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(value);
|
||||||
if (cs != null) {
|
if (cs != null) {
|
||||||
String ref = (String) cs.getUserData("path");
|
String ref = (String) cs.getUserData("path");
|
||||||
ref = adjustForPath(ref);
|
ref = adjustForPath(ref);
|
||||||
|
@ -427,69 +299,19 @@ public class TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String adjustForPath(String ref) {
|
private String adjustForPath(String ref) {
|
||||||
if (prefix == null)
|
if (getContext().getPrefix() == null)
|
||||||
return ref;
|
return ref;
|
||||||
else
|
else
|
||||||
return prefix+ref;
|
return getContext().getPrefix()+ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void addTelecom(XhtmlNode p, ContactPoint c) {
|
|
||||||
if (c.getSystem() == ContactPointSystem.PHONE) {
|
|
||||||
p.tx("Phone: "+c.getValue());
|
|
||||||
} else if (c.getSystem() == ContactPointSystem.FAX) {
|
|
||||||
p.tx("Fax: "+c.getValue());
|
|
||||||
} else if (c.getSystem() == ContactPointSystem.EMAIL) {
|
|
||||||
p.ah( "mailto:"+c.getValue()).addText(c.getValue());
|
|
||||||
} else if (c.getSystem() == ContactPointSystem.URL) {
|
|
||||||
if (c.getValue().length() > 30)
|
|
||||||
p.ah(c.getValue()).addText(c.getValue().substring(0, 30)+"...");
|
|
||||||
else
|
|
||||||
p.ah(c.getValue()).addText(c.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected String getDisplayForConcept(String system, String value) {
|
protected String getDisplayForConcept(String system, String value) {
|
||||||
if (value == null || system == null)
|
if (value == null || system == null)
|
||||||
return null;
|
return null;
|
||||||
ValidationResult cl = context.validateCode(terminologyServiceOptions, system, value, null);
|
ValidationResult cl = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), system, value, null);
|
||||||
return cl == null ? null : cl.getDisplay();
|
return cl == null ? null : cl.getDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected String describeLang(String lang) {
|
|
||||||
ValueSet v = context.fetchResource(ValueSet.class, "http://hl7.org/fhir/ValueSet/languages");
|
|
||||||
if (v != null) {
|
|
||||||
ConceptReferenceComponent l = null;
|
|
||||||
for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) {
|
|
||||||
if (cc.getCode().equals(lang))
|
|
||||||
l = cc;
|
|
||||||
}
|
|
||||||
if (l == null) {
|
|
||||||
if (lang.contains("-"))
|
|
||||||
lang = lang.substring(0, lang.indexOf("-"));
|
|
||||||
for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) {
|
|
||||||
if (cc.getCode().equals(lang) || cc.getCode().startsWith(lang+"-"))
|
|
||||||
l = cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l != null) {
|
|
||||||
if (lang.contains("-"))
|
|
||||||
lang = lang.substring(0, lang.indexOf("-"));
|
|
||||||
String en = l.getDisplay();
|
|
||||||
String nativelang = null;
|
|
||||||
for (ConceptReferenceDesignationComponent cd : l.getDesignation()) {
|
|
||||||
if (cd.getLanguage().equals(lang))
|
|
||||||
nativelang = cd.getValue();
|
|
||||||
}
|
|
||||||
if (nativelang == null)
|
|
||||||
return en+" ("+lang+")";
|
|
||||||
else
|
|
||||||
return nativelang+" ("+en+", "+lang+")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lang;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hl7.fhir.r5.terminologies;
|
package org.hl7.fhir.r5.renderers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -12,7 +12,6 @@ import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
import org.hl7.fhir.r5.model.BooleanType;
|
import org.hl7.fhir.r5.model.BooleanType;
|
||||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
|
@ -21,6 +20,7 @@ import org.hl7.fhir.r5.model.ConceptMap;
|
||||||
import org.hl7.fhir.r5.model.DataType;
|
import org.hl7.fhir.r5.model.DataType;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
import org.hl7.fhir.r5.model.ExtensionHelper;
|
import org.hl7.fhir.r5.model.ExtensionHelper;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.UriType;
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
|
@ -28,6 +28,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||||
|
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||||
|
@ -35,12 +36,16 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer.ConceptMapRenderInstructions;
|
import org.hl7.fhir.r5.renderers.TerminologyRenderer.ConceptMapRenderInstructions;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.r5.utils.NarrativeGenerator.ResourceContext;
|
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
@ -49,81 +54,59 @@ import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
public class ValueSetRenderer extends TerminologyRenderer {
|
public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
|
public ValueSetRenderer(RenderingContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueSetRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||||
|
super(context, rcontext);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String ABSTRACT_CODE_HINT = "This code is not selectable ('Abstract')";
|
private static final String ABSTRACT_CODE_HINT = "This code is not selectable ('Abstract')";
|
||||||
|
|
||||||
private String tooCostlyNoteEmpty;
|
|
||||||
private String tooCostlyNoteNotEmpty;
|
|
||||||
private String tooCostlyNoteEmptyDependent;
|
|
||||||
private String tooCostlyNoteNotEmptyDependent;
|
|
||||||
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
|
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
|
||||||
|
|
||||||
/**
|
public void render(ValueSet vs) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
*
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
* @param mode - whether we are rendering for a resource directly, or for an IG
|
boolean hasExtensions = render(x, vs);
|
||||||
* @param context - common services (terminology server, code system cache etc)
|
inject(vs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
* @param markdown - markdown processing engine of the correct sort for the version applicable
|
|
||||||
* @param prefix - the path to the base FHIR specification
|
|
||||||
* @param lang - the language to use (null for the default)
|
|
||||||
*/
|
|
||||||
public ValueSetRenderer(TerminologyRendererMode mode, IWorkerContext context, MarkDownProcessor markdown, String prefix, String lang) {
|
|
||||||
super(mode, context, markdown, prefix, lang);
|
|
||||||
renderingMaps.add(new ConceptMapRenderInstructions("Canonical Status", "http://hl7.org/fhir/ValueSet/resource-status", false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTooCostlyNoteEmpty() {
|
public boolean render(XhtmlNode x, ValueSet vs) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
return tooCostlyNoteEmpty;
|
return render(x, vs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTooCostlyNoteEmpty(String tooCostlyNoteEmpty) {
|
public boolean render(XhtmlNode x, ValueSet vs, boolean header) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
this.tooCostlyNoteEmpty = tooCostlyNoteEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTooCostlyNoteNotEmpty() {
|
|
||||||
return tooCostlyNoteNotEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTooCostlyNoteNotEmpty(String tooCostlyNoteNotEmpty) {
|
|
||||||
this.tooCostlyNoteNotEmpty = tooCostlyNoteNotEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTooCostlyNoteEmptyDependent() {
|
|
||||||
return tooCostlyNoteEmptyDependent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTooCostlyNoteEmptyDependent(String tooCostlyNoteEmptyDependent) {
|
|
||||||
this.tooCostlyNoteEmptyDependent = tooCostlyNoteEmptyDependent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTooCostlyNoteNotEmptyDependent() {
|
|
||||||
return tooCostlyNoteNotEmptyDependent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTooCostlyNoteNotEmptyDependent(String tooCostlyNoteNotEmptyDependent) {
|
|
||||||
this.tooCostlyNoteNotEmptyDependent = tooCostlyNoteNotEmptyDependent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean render(ResourceContext rcontext, XhtmlNode x, ValueSet vs, ValueSet src, boolean header) throws FHIRFormatError, DefinitionException, IOException {
|
|
||||||
List<UsedConceptMap> maps = findReleventMaps(vs);
|
List<UsedConceptMap> maps = findReleventMaps(vs);
|
||||||
|
|
||||||
boolean hasExtensions;
|
boolean hasExtensions;
|
||||||
if (vs.hasExpansion()) {
|
if (vs.hasExpansion()) {
|
||||||
// for now, we just accept an expansion if there is one
|
// for now, we just accept an expansion if there is one
|
||||||
hasExtensions = generateExpansion(x, vs, src, header, maps);
|
hasExtensions = generateExpansion(x, vs, header, maps);
|
||||||
} else {
|
} else {
|
||||||
hasExtensions = generateComposition(rcontext, x, vs, header, maps);
|
hasExtensions = generateComposition(x, vs, header, maps);
|
||||||
}
|
}
|
||||||
return hasExtensions;
|
return hasExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void describe(XhtmlNode x, ValueSet vs) {
|
||||||
|
x.tx(display(vs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String display(ValueSet vs) {
|
||||||
|
return vs.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<UsedConceptMap> findReleventMaps(ValueSet vs) throws FHIRException {
|
private List<UsedConceptMap> findReleventMaps(ValueSet vs) throws FHIRException {
|
||||||
List<UsedConceptMap> res = new ArrayList<UsedConceptMap>();
|
List<UsedConceptMap> res = new ArrayList<UsedConceptMap>();
|
||||||
for (CanonicalResource md : context.allConformanceResources()) {
|
for (CanonicalResource md : getContext().getWorker().allConformanceResources()) {
|
||||||
if (md instanceof ConceptMap) {
|
if (md instanceof ConceptMap) {
|
||||||
ConceptMap cm = (ConceptMap) md;
|
ConceptMap cm = (ConceptMap) md;
|
||||||
if (isSource(vs, cm.getSource())) {
|
if (isSource(vs, cm.getSource())) {
|
||||||
ConceptMapRenderInstructions re = findByTarget(cm.getTarget());
|
ConceptMapRenderInstructions re = findByTarget(cm.getTarget());
|
||||||
if (re != null) {
|
if (re != null) {
|
||||||
ValueSet vst = cm.hasTarget() ? context.fetchResource(ValueSet.class, cm.hasTargetCanonicalType() ? cm.getTargetCanonicalType().getValue() : cm.getTargetUriType().asStringValue()) : null;
|
ValueSet vst = cm.hasTarget() ? getContext().getWorker().fetchResource(ValueSet.class, cm.hasTargetCanonicalType() ? cm.getTargetCanonicalType().getValue() : cm.getTargetUriType().asStringValue()) : null;
|
||||||
res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm));
|
res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,17 +114,17 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
// Map<ConceptMap, String> mymaps = new HashMap<ConceptMap, String>();
|
// Map<ConceptMap, String> mymaps = new HashMap<ConceptMap, String>();
|
||||||
// for (ConceptMap a : context.findMapsForSource(vs.getUrl())) {
|
// for (ConceptMap a : context.getWorker().findMapsForSource(vs.getUrl())) {
|
||||||
// String url = "";
|
// String url = "";
|
||||||
// ValueSet vsr = context.fetchResource(ValueSet.class, ((Reference) a.getTarget()).getReference());
|
// ValueSet vsr = context.getWorker().fetchResource(ValueSet.class, ((Reference) a.getTarget()).getReference());
|
||||||
// if (vsr != null)
|
// if (vsr != null)
|
||||||
// url = (String) vsr.getUserData("filename");
|
// url = (String) vsr.getUserData("filename");
|
||||||
// mymaps.put(a, url);
|
// mymaps.put(a, url);
|
||||||
// }
|
// }
|
||||||
// Map<ConceptMap, String> mymaps = new HashMap<ConceptMap, String>();
|
// Map<ConceptMap, String> mymaps = new HashMap<ConceptMap, String>();
|
||||||
// for (ConceptMap a : context.findMapsForSource(cs.getValueSet())) {
|
// for (ConceptMap a : context.getWorker().findMapsForSource(cs.getValueSet())) {
|
||||||
// String url = "";
|
// String url = "";
|
||||||
// ValueSet vsr = context.fetchResource(ValueSet.class, ((Reference) a.getTarget()).getReference());
|
// ValueSet vsr = context.getWorker().fetchResource(ValueSet.class, ((Reference) a.getTarget()).getReference());
|
||||||
// if (vsr != null)
|
// if (vsr != null)
|
||||||
// url = (String) vsr.getUserData("filename");
|
// url = (String) vsr.getUserData("filename");
|
||||||
// mymaps.put(a, url);
|
// mymaps.put(a, url);
|
||||||
|
@ -152,7 +135,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
// ConceptMap cm = (ConceptMap) r;
|
// ConceptMap cm = (ConceptMap) r;
|
||||||
// if (((Reference) cm.getSource()).getReference().equals(cs.getValueSet())) {
|
// if (((Reference) cm.getSource()).getReference().equals(cs.getValueSet())) {
|
||||||
// String url = "";
|
// String url = "";
|
||||||
// ValueSet vsr = context.fetchResource(ValueSet.class, ((Reference) cm.getTarget()).getReference());
|
// ValueSet vsr = context.getWorker().fetchResource(ValueSet.class, ((Reference) cm.getTarget()).getReference());
|
||||||
// if (vsr != null)
|
// if (vsr != null)
|
||||||
// url = (String) vsr.getUserData("filename");
|
// url = (String) vsr.getUserData("filename");
|
||||||
// mymaps.put(cm, url);
|
// mymaps.put(cm, url);
|
||||||
|
@ -165,7 +148,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
return vs.hasUrl() && source != null && vs.getUrl().equals(source.primitiveValue());
|
return vs.hasUrl() && source != null && vs.getUrl().equals(source.primitiveValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateExpansion(XhtmlNode x, ValueSet vs, ValueSet src, boolean header, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
private boolean generateExpansion(XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
boolean hasExtensions = false;
|
boolean hasExtensions = false;
|
||||||
List<String> langs = new ArrayList<String>();
|
List<String> langs = new ArrayList<String>();
|
||||||
|
|
||||||
|
@ -183,9 +166,9 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
boolean other = false;
|
boolean other = false;
|
||||||
for (Extension ex : exl) {
|
for (Extension ex : exl) {
|
||||||
if (ex.getValue() instanceof BooleanType) {
|
if (ex.getValue() instanceof BooleanType) {
|
||||||
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? tooCostlyNoteEmpty : tooCostlyNoteNotEmpty );
|
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmpty() : getContext().getTooCostlyNoteNotEmpty());
|
||||||
} else if (!other) {
|
} else if (!other) {
|
||||||
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? tooCostlyNoteEmptyDependent : tooCostlyNoteNotEmptyDependent );
|
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmptyDependent() : getContext().getTooCostlyNoteNotEmptyDependent());
|
||||||
other = true;
|
other = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,14 +213,14 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
doSystem = false;
|
doSystem = false;
|
||||||
XhtmlNode p = x.para();
|
XhtmlNode p = x.para();
|
||||||
p.tx("All codes from system ");
|
p.tx("All codes from system ");
|
||||||
allCS = context.fetchCodeSystem(vs.getExpansion().getContains().get(0).getSystem());
|
allCS = getContext().getWorker().fetchCodeSystem(vs.getExpansion().getContains().get(0).getSystem());
|
||||||
String ref = null;
|
String ref = null;
|
||||||
if (allCS != null)
|
if (allCS != null)
|
||||||
ref = getCsRef(allCS);
|
ref = getCsRef(allCS);
|
||||||
if (ref == null)
|
if (ref == null)
|
||||||
p.code(vs.getExpansion().getContains().get(0).getSystem());
|
p.code(vs.getExpansion().getContains().get(0).getSystem());
|
||||||
else
|
else
|
||||||
p.ah(prefix+ref).code(vs.getExpansion().getContains().get(0).getSystem());
|
p.ah(getContext().getPrefix()+ref).code(vs.getExpansion().getContains().get(0).getSystem());
|
||||||
}
|
}
|
||||||
XhtmlNode t = x.table( "codes");
|
XhtmlNode t = x.table( "codes");
|
||||||
XhtmlNode tr = t.tr();
|
XhtmlNode tr = t.tr();
|
||||||
|
@ -319,7 +302,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
if (vs.hasCompose()) {
|
if (vs.hasCompose()) {
|
||||||
if (vs.getCompose().hasExclude()) {
|
if (vs.getCompose().hasExclude()) {
|
||||||
try {
|
try {
|
||||||
ValueSetExpansionOutcome vse = context.expandVS(vs, true, false);
|
ValueSetExpansionOutcome vse = getContext().getWorker().expandVS(vs, true, false);
|
||||||
count = 0;
|
count = 0;
|
||||||
count += conceptCount(vse.getValueset().getExpansion().getContains());
|
count += conceptCount(vse.getValueset().getExpansion().getContains());
|
||||||
return count;
|
return count;
|
||||||
|
@ -350,7 +333,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCSRef(XhtmlNode x, String url) {
|
private void addCSRef(XhtmlNode x, String url) {
|
||||||
CodeSystem cs = context.fetchCodeSystem(url);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(url);
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
x.code(url);
|
x.code(url);
|
||||||
} else if (cs.hasUserData("path")) {
|
} else if (cs.hasUserData("path")) {
|
||||||
|
@ -419,7 +402,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
x.tx("Loinc v"+v);
|
x.tx("Loinc v"+v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CanonicalResource cr = (CanonicalResource) context.fetchResource(Resource.class, u+"|"+v);
|
CanonicalResource cr = (CanonicalResource) getContext().getWorker().fetchResource(Resource.class, u+"|"+v);
|
||||||
if (cr != null) {
|
if (cr != null) {
|
||||||
if (cr.hasUserData("path")) {
|
if (cr.hasUserData("path")) {
|
||||||
x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")");
|
x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")");
|
||||||
|
@ -548,7 +531,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
private boolean checkDoDefinition(List<ValueSetExpansionContainsComponent> contains) {
|
private boolean checkDoDefinition(List<ValueSetExpansionContainsComponent> contains) {
|
||||||
for (ValueSetExpansionContainsComponent c : contains) {
|
for (ValueSetExpansionContainsComponent c : contains) {
|
||||||
CodeSystem cs = context.fetchCodeSystem(c.getSystem());
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(c.getSystem());
|
||||||
if (cs != null)
|
if (cs != null)
|
||||||
return true;
|
return true;
|
||||||
if (checkDoDefinition(c.getContains()))
|
if (checkDoDefinition(c.getContains()))
|
||||||
|
@ -570,7 +553,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCsRef(String system) {
|
private String getCsRef(String system) {
|
||||||
CodeSystem cs = context.fetchCodeSystem(system);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(system);
|
||||||
return getCsRef(cs);
|
return getCsRef(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,7 +593,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
if (doDefinition) {
|
if (doDefinition) {
|
||||||
CodeSystem cs = allCS;
|
CodeSystem cs = allCS;
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
cs = context.fetchCodeSystem(c.getSystem());
|
cs = getContext().getWorker().fetchCodeSystem(c.getSystem());
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
if (cs != null)
|
if (cs != null)
|
||||||
td.addText(CodeSystemUtilities.getCodeDefinition(cs, c.getCode()));
|
td.addText(CodeSystemUtilities.getCodeDefinition(cs, c.getCode()));
|
||||||
|
@ -657,7 +640,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodeToTable(boolean isAbstract, String system, String code, String display, XhtmlNode td) {
|
private void addCodeToTable(boolean isAbstract, String system, String code, String display, XhtmlNode td) {
|
||||||
CodeSystem e = context.fetchCodeSystem(system);
|
CodeSystem e = getContext().getWorker().fetchCodeSystem(system);
|
||||||
if (e == null || e.getContent() != org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode.COMPLETE) {
|
if (e == null || e.getContent() != org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode.COMPLETE) {
|
||||||
if (isAbstract)
|
if (isAbstract)
|
||||||
td.i().setAttribute("title", ABSTRACT_CODE_HINT).addText(code);
|
td.i().setAttribute("title", ABSTRACT_CODE_HINT).addText(code);
|
||||||
|
@ -668,7 +651,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
} else
|
} else
|
||||||
td.addText(code);
|
td.addText(code);
|
||||||
} else {
|
} else {
|
||||||
String href = prefix+getCsRef(e);
|
String href = getContext().getPrefix()+getCsRef(e);
|
||||||
if (href.contains("#"))
|
if (href.contains("#"))
|
||||||
href = href + "-"+Utilities.nmtokenize(code);
|
href = href + "-"+Utilities.nmtokenize(code);
|
||||||
else
|
else
|
||||||
|
@ -688,17 +671,17 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRefToCode(XhtmlNode td, String target, String vslink, String code) {
|
private void addRefToCode(XhtmlNode td, String target, String vslink, String code) {
|
||||||
CodeSystem cs = context.fetchCodeSystem(target);
|
CodeSystem cs = getContext().getWorker().fetchCodeSystem(target);
|
||||||
String cslink = getCsRef(cs);
|
String cslink = getCsRef(cs);
|
||||||
XhtmlNode a = null;
|
XhtmlNode a = null;
|
||||||
if (cslink != null)
|
if (cslink != null)
|
||||||
a = td.ah(prefix+cslink+"#"+cs.getId()+"-"+code);
|
a = td.ah(getContext().getPrefix()+cslink+"#"+cs.getId()+"-"+code);
|
||||||
else
|
else
|
||||||
a = td.ah(prefix+vslink+"#"+code);
|
a = td.ah(getContext().getPrefix()+vslink+"#"+code);
|
||||||
a.addText(code);
|
a.addText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateComposition(ResourceContext rcontext, XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
private boolean generateComposition(XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
||||||
boolean hasExtensions = false;
|
boolean hasExtensions = false;
|
||||||
List<String> langs = new ArrayList<String>();
|
List<String> langs = new ArrayList<String>();
|
||||||
|
|
||||||
|
@ -711,17 +694,17 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
XhtmlNode ul = x.ul();
|
XhtmlNode ul = x.ul();
|
||||||
if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0) {
|
if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0) {
|
||||||
hasExtensions = genInclude(rcontext, ul, vs.getCompose().getInclude().get(0), "Include", langs, maps) || hasExtensions;
|
hasExtensions = genInclude(ul, vs.getCompose().getInclude().get(0), "Include", langs, maps) || hasExtensions;
|
||||||
} else {
|
} else {
|
||||||
XhtmlNode p = x.para();
|
XhtmlNode p = x.para();
|
||||||
p.tx("This value set includes codes based on the following rules:");
|
p.tx("This value set includes codes based on the following rules:");
|
||||||
|
|
||||||
XhtmlNode li;
|
XhtmlNode li;
|
||||||
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
|
||||||
hasExtensions = genInclude(rcontext, ul, inc, "Include", langs, maps) || hasExtensions;
|
hasExtensions = genInclude(ul, inc, "Include", langs, maps) || hasExtensions;
|
||||||
}
|
}
|
||||||
for (ConceptSetComponent exc : vs.getCompose().getExclude()) {
|
for (ConceptSetComponent exc : vs.getCompose().getExclude()) {
|
||||||
hasExtensions = genInclude(rcontext, ul, exc, "Exclude", langs, maps) || hasExtensions;
|
hasExtensions = genInclude(ul, exc, "Exclude", langs, maps) || hasExtensions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,11 +728,11 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
return hasExtensions;
|
return hasExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean genInclude(ResourceContext rcontext, XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, List<UsedConceptMap> maps) throws FHIRException, IOException {
|
||||||
boolean hasExtensions = false;
|
boolean hasExtensions = false;
|
||||||
XhtmlNode li;
|
XhtmlNode li;
|
||||||
li = ul.li();
|
li = ul.li();
|
||||||
CodeSystem e = context.fetchCodeSystem(inc.getSystem());
|
CodeSystem e = getContext().getWorker().fetchCodeSystem(inc.getSystem());
|
||||||
|
|
||||||
if (inc.hasSystem()) {
|
if (inc.hasSystem()) {
|
||||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||||
|
@ -823,7 +806,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
} else {
|
} else {
|
||||||
li.tx(f.getProperty()+" "+describe(f.getOp())+" ");
|
li.tx(f.getProperty()+" "+describe(f.getOp())+" ");
|
||||||
if (e != null && codeExistsInValueSet(e, f.getValue())) {
|
if (e != null && codeExistsInValueSet(e, f.getValue())) {
|
||||||
String href = prefix+getCsRef(e);
|
String href = getContext().getPrefix()+getCsRef(e);
|
||||||
if (href.contains("#"))
|
if (href.contains("#"))
|
||||||
href = href + "-"+Utilities.nmtokenize(f.getValue());
|
href = href + "-"+Utilities.nmtokenize(f.getValue());
|
||||||
else
|
else
|
||||||
|
@ -831,7 +814,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
li.ah(href).addText(f.getValue());
|
li.ah(href).addText(f.getValue());
|
||||||
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
} else if ("concept".equals(f.getProperty()) && inc.hasSystem()) {
|
||||||
li.addText(f.getValue());
|
li.addText(f.getValue());
|
||||||
ValidationResult vr = context.validateCode(terminologyServiceOptions, inc.getSystem(), f.getValue(), null);
|
ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), f.getValue(), null);
|
||||||
if (vr.isOk()) {
|
if (vr.isOk()) {
|
||||||
li.tx(" ("+vr.getDisplay()+")");
|
li.tx(" ("+vr.getDisplay()+")");
|
||||||
}
|
}
|
||||||
|
@ -853,7 +836,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
li.tx(", ");
|
li.tx(", ");
|
||||||
AddVsRef(rcontext, vs.asStringValue(), li);
|
AddVsRef(vs.asStringValue(), li);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -864,7 +847,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
li.tx(", ");
|
li.tx(", ");
|
||||||
AddVsRef(rcontext, vs.asStringValue(), li);
|
AddVsRef(vs.asStringValue(), li);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasExtensions;
|
return hasExtensions;
|
||||||
|
@ -877,7 +860,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
// first, look in the code systems
|
// first, look in the code systems
|
||||||
if (e == null)
|
if (e == null)
|
||||||
e = context.fetchCodeSystem(inc.getSystem());
|
e = getContext().getWorker().fetchCodeSystem(inc.getSystem());
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
ConceptDefinitionComponent v = getConceptForCode(e.getConcept(), code);
|
ConceptDefinitionComponent v = getConceptForCode(e.getConcept(), code);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
|
@ -887,10 +870,10 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
if (noSlowLookup)
|
if (noSlowLookup)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (!context.hasCache()) {
|
if (!getContext().getWorker().hasCache()) {
|
||||||
ValueSetExpansionComponent vse;
|
ValueSetExpansionComponent vse;
|
||||||
try {
|
try {
|
||||||
ValueSetExpansionOutcome vso = context.expandVS(inc, false);
|
ValueSetExpansionOutcome vso = getContext().getWorker().expandVS(inc, false);
|
||||||
ValueSet valueset = vso.getValueset();
|
ValueSet valueset = vso.getValueset();
|
||||||
if (valueset == null)
|
if (valueset == null)
|
||||||
throw new TerminologyServiceException("Error Expanding ValueSet: "+vso.getError());
|
throw new TerminologyServiceException("Error Expanding ValueSet: "+vso.getError());
|
||||||
|
@ -906,7 +889,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.validateCode(terminologyServiceOptions, inc.getSystem(), code, null).asConceptDefinition();
|
return getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), code, null).asConceptDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> list, String code) {
|
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> list, String code) {
|
|
@ -0,0 +1,116 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapper;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class BaseWrappers {
|
||||||
|
|
||||||
|
public interface RendererWrapper {
|
||||||
|
public ResourceRenderer getRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PropertyWrapper extends RendererWrapper {
|
||||||
|
public String getName();
|
||||||
|
public boolean hasValues();
|
||||||
|
public List<BaseWrapper> getValues();
|
||||||
|
public String getTypeCode();
|
||||||
|
public String getDefinition();
|
||||||
|
public int getMinCardinality();
|
||||||
|
public int getMaxCardinality();
|
||||||
|
public StructureDefinition getStructure();
|
||||||
|
public BaseWrapper value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface WrapperBase extends RendererWrapper {
|
||||||
|
public boolean has(String name);
|
||||||
|
public Base get(String name) throws UnsupportedEncodingException, FHIRException, IOException;
|
||||||
|
public List<BaseWrapper> children(String name) throws UnsupportedEncodingException, FHIRException, IOException;
|
||||||
|
public List<PropertyWrapper> children();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResourceWrapper extends WrapperBase {
|
||||||
|
public List<ResourceWrapper> getContained();
|
||||||
|
public String getId();
|
||||||
|
public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException;
|
||||||
|
public String getName();
|
||||||
|
public void describe(XhtmlNode x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface BaseWrapper extends WrapperBase {
|
||||||
|
public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException;
|
||||||
|
public PropertyWrapper getChildByName(String tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class RendererWrapperImpl implements RendererWrapper {
|
||||||
|
protected ResourceRenderer renderer;
|
||||||
|
|
||||||
|
public RendererWrapperImpl(ResourceRenderer renderer) {
|
||||||
|
super();
|
||||||
|
this.renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceRenderer getRenderer() {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String tail(String path) {
|
||||||
|
return path.substring(path.lastIndexOf(".")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class WrapperBaseImpl extends RendererWrapperImpl implements WrapperBase {
|
||||||
|
|
||||||
|
public WrapperBaseImpl(ResourceRenderer renderer) {
|
||||||
|
super(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(String name) {
|
||||||
|
for (PropertyWrapper p : children()) {
|
||||||
|
if (p.getName().equals(name)) {
|
||||||
|
return p.hasValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base get(String name) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||||
|
for (PropertyWrapper p : children()) {
|
||||||
|
if (p.getName().equals(name)) {
|
||||||
|
if (p.hasValues()) {
|
||||||
|
return p.getValues().get(0).getBase();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaseWrapper> children(String name) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||||
|
for (PropertyWrapper p : children()) {
|
||||||
|
if (p.getName().equals(name)) {
|
||||||
|
List<BaseWrapper> res = new ArrayList<>();
|
||||||
|
for (BaseWrapper b : p.getValues()) {
|
||||||
|
res.add(b);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||||
|
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl;
|
||||||
|
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||||
|
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||||
|
import org.hl7.fhir.utilities.xml.XmlGenerator;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
public class DOMWrappers {
|
||||||
|
|
||||||
|
|
||||||
|
public static class BaseWrapperElement extends WrapperBaseImpl implements BaseWrapper {
|
||||||
|
private Element element;
|
||||||
|
private String type;
|
||||||
|
private StructureDefinition structure;
|
||||||
|
private ElementDefinition definition;
|
||||||
|
private List<ElementDefinition> children;
|
||||||
|
private List<PropertyWrapper> list;
|
||||||
|
|
||||||
|
public BaseWrapperElement(ResourceRenderer renderer, Element element, String type, StructureDefinition structure, ElementDefinition definition) {
|
||||||
|
super(renderer);
|
||||||
|
this.element = element;
|
||||||
|
this.type = type;
|
||||||
|
this.structure = structure;
|
||||||
|
this.definition = definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException {
|
||||||
|
if (type == null || type.equals("Resource") || type.equals("BackboneElement") || type.equals("Element"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String xml;
|
||||||
|
try {
|
||||||
|
xml = new XmlGenerator().generate(element);
|
||||||
|
} catch (org.hl7.fhir.exceptions.FHIRException e) {
|
||||||
|
throw new FHIRException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return renderer.parseType(xml, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
if (list == null) {
|
||||||
|
children = renderer.getContext().getProfileUtilities().getChildList(structure, definition);
|
||||||
|
list = new ArrayList<PropertyWrapper>();
|
||||||
|
for (ElementDefinition child : children) {
|
||||||
|
List<Element> elements = new ArrayList<Element>();
|
||||||
|
XMLUtil.getNamedChildrenWithWildcard(element, tail(child.getPath()), elements);
|
||||||
|
list.add(new PropertyWrapperElement(renderer, structure, child, elements));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyWrapper getChildByName(String name) {
|
||||||
|
for (PropertyWrapper p : children())
|
||||||
|
if (p.getName().equals(name))
|
||||||
|
return p;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PropertyWrapperElement extends RendererWrapperImpl implements PropertyWrapper {
|
||||||
|
|
||||||
|
private StructureDefinition structure;
|
||||||
|
private ElementDefinition definition;
|
||||||
|
private List<Element> values;
|
||||||
|
private List<BaseWrapper> list;
|
||||||
|
|
||||||
|
public PropertyWrapperElement(ResourceRenderer renderer, StructureDefinition structure, ElementDefinition definition, List<Element> values) {
|
||||||
|
super(renderer);
|
||||||
|
this.structure = structure;
|
||||||
|
this.definition = definition;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return tail(definition.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasValues() {
|
||||||
|
return values.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaseWrapper> getValues() {
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<BaseWrapper>();
|
||||||
|
for (Element e : values)
|
||||||
|
list.add(new BaseWrapperElement(renderer, e, determineType(e), structure, definition));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
private String determineType(Element e) {
|
||||||
|
if (definition.getType().isEmpty())
|
||||||
|
return null;
|
||||||
|
if (definition.getType().size() == 1) {
|
||||||
|
if (definition.getType().get(0).getWorkingCode().equals("Element") || definition.getType().get(0).getWorkingCode().equals("BackboneElement"))
|
||||||
|
return null;
|
||||||
|
return definition.getType().get(0).getWorkingCode();
|
||||||
|
}
|
||||||
|
String t = e.getNodeName().substring(tail(definition.getPath()).length()-3);
|
||||||
|
|
||||||
|
if (isPrimitive(Utilities.uncapitalize(t)))
|
||||||
|
return Utilities.uncapitalize(t);
|
||||||
|
else
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPrimitive(String code) {
|
||||||
|
StructureDefinition sd = renderer.getContext().getWorker().fetchTypeDefinition(code);
|
||||||
|
return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTypeCode() {
|
||||||
|
if (definition == null || definition.getType().size() != 1)
|
||||||
|
throw new Error("not handled");
|
||||||
|
return definition.getType().get(0).getWorkingCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefinition() {
|
||||||
|
if (definition == null)
|
||||||
|
throw new Error("not handled");
|
||||||
|
return definition.getDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinCardinality() {
|
||||||
|
if (definition == null)
|
||||||
|
throw new Error("not handled");
|
||||||
|
return definition.getMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxCardinality() {
|
||||||
|
if (definition == null)
|
||||||
|
throw new Error("not handled");
|
||||||
|
return definition.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(definition.getMax());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructureDefinition getStructure() {
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseWrapper value() {
|
||||||
|
if (getValues().size() != 1)
|
||||||
|
throw new Error("Access single value, but value count is "+getValues().size());
|
||||||
|
return getValues().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceWrapperElement extends WrapperBaseImpl implements ResourceWrapper {
|
||||||
|
|
||||||
|
private Element wrapped;
|
||||||
|
private StructureDefinition definition;
|
||||||
|
private List<ResourceWrapper> list;
|
||||||
|
private List<PropertyWrapper> list2;
|
||||||
|
|
||||||
|
public ResourceWrapperElement(ResourceRenderer renderer, Element wrapped, StructureDefinition definition) {
|
||||||
|
super(renderer);
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
this.definition = definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResourceWrapper> getContained() {
|
||||||
|
if (list == null) {
|
||||||
|
List<Element> children = new ArrayList<Element>();
|
||||||
|
XMLUtil.getNamedChildren(wrapped, "contained", children);
|
||||||
|
list = new ArrayList<ResourceWrapper>();
|
||||||
|
for (Element e : children) {
|
||||||
|
Element c = XMLUtil.getFirstChild(e);
|
||||||
|
list.add(new ResourceWrapperElement(renderer, c, renderer.getContext().getWorker().fetchTypeDefinition(c.getNodeName())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return XMLUtil.getNamedChildValue(wrapped, "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException {
|
||||||
|
Element txt = XMLUtil.getNamedChild(wrapped, "text");
|
||||||
|
if (txt == null)
|
||||||
|
return null;
|
||||||
|
Element div = XMLUtil.getNamedChild(txt, "div");
|
||||||
|
if (div == null)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
return new XhtmlParser().parse(new XmlGenerator().generate(div), "div");
|
||||||
|
} catch (org.hl7.fhir.exceptions.FHIRFormatError e) {
|
||||||
|
throw new FHIRFormatError(e.getMessage(), e);
|
||||||
|
} catch (org.hl7.fhir.exceptions.FHIRException e) {
|
||||||
|
throw new FHIRException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return wrapped.getNodeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
if (list2 == null) {
|
||||||
|
List<ElementDefinition> children = renderer.getContext().getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0));
|
||||||
|
list2 = new ArrayList<PropertyWrapper>();
|
||||||
|
for (ElementDefinition child : children) {
|
||||||
|
List<Element> elements = new ArrayList<Element>();
|
||||||
|
XMLUtil.getNamedChildrenWithWildcard(wrapped, tail(child.getPath()), elements);
|
||||||
|
list2.add(new PropertyWrapperElement(renderer, definition, child, elements));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describe(XhtmlNode x) {
|
||||||
|
throw new Error("Not done yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
|
import org.hl7.fhir.r5.model.DomainResource;
|
||||||
|
import org.hl7.fhir.r5.model.Encounter;
|
||||||
|
import org.hl7.fhir.r5.model.Patient;
|
||||||
|
import org.hl7.fhir.r5.model.Property;
|
||||||
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.renderers.EncounterRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.PatientRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl;
|
||||||
|
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class DirectWrappers {
|
||||||
|
|
||||||
|
public static class PropertyWrapperDirect extends RendererWrapperImpl implements PropertyWrapper {
|
||||||
|
private Property wrapped;
|
||||||
|
private List<BaseWrapper> list;
|
||||||
|
|
||||||
|
public PropertyWrapperDirect(ResourceRenderer renderer, Property wrapped) {
|
||||||
|
super(renderer);
|
||||||
|
if (wrapped == null)
|
||||||
|
throw new Error("wrapped == null");
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return wrapped.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property getWrapped() {
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasValues() {
|
||||||
|
return wrapped.hasValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaseWrapper> getValues() {
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<BaseWrapper>();
|
||||||
|
for (Base b : wrapped.getValues())
|
||||||
|
list.add(b == null ? null : new BaseWrapperDirect(renderer, b));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTypeCode() {
|
||||||
|
return wrapped.getTypeCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefinition() {
|
||||||
|
return wrapped.getDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinCardinality() {
|
||||||
|
return wrapped.getMinCardinality();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxCardinality() {
|
||||||
|
return wrapped.getMinCardinality();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructureDefinition getStructure() {
|
||||||
|
return wrapped.getStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseWrapper value() {
|
||||||
|
if (getValues().size() != 1)
|
||||||
|
throw new Error("Access single value, but value count is "+getValues().size());
|
||||||
|
return getValues().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "#."+wrapped.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BaseWrapperDirect extends WrapperBaseImpl implements BaseWrapper {
|
||||||
|
private Base wrapped;
|
||||||
|
private List<PropertyWrapper> list;
|
||||||
|
|
||||||
|
public BaseWrapperDirect(ResourceRenderer renderer, Base wrapped) {
|
||||||
|
super(renderer);
|
||||||
|
if (wrapped == null)
|
||||||
|
throw new Error("wrapped == null");
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base getBase() {
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<PropertyWrapper>();
|
||||||
|
for (Property p : wrapped.children())
|
||||||
|
list.add(new PropertyWrapperDirect(renderer, p));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyWrapper getChildByName(String name) {
|
||||||
|
Property p = wrapped.getChildByName(name);
|
||||||
|
if (p == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return new PropertyWrapperDirect(renderer, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceWrapperDirect extends WrapperBaseImpl implements ResourceWrapper {
|
||||||
|
private Resource wrapped;
|
||||||
|
|
||||||
|
public ResourceWrapperDirect(ResourceRenderer renderer, Resource wrapped) {
|
||||||
|
super(renderer);
|
||||||
|
if (wrapped == null)
|
||||||
|
throw new Error("wrapped == null");
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResourceWrapper> getContained() {
|
||||||
|
List<ResourceWrapper> list = new ArrayList<ResourceWrapper>();
|
||||||
|
if (wrapped instanceof DomainResource) {
|
||||||
|
DomainResource dr = (DomainResource) wrapped;
|
||||||
|
for (Resource c : dr.getContained()) {
|
||||||
|
list.add(new ResourceWrapperDirect(renderer, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return wrapped.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XhtmlNode getNarrative() {
|
||||||
|
if (wrapped instanceof DomainResource) {
|
||||||
|
DomainResource dr = (DomainResource) wrapped;
|
||||||
|
if (dr.hasText() && dr.getText().hasDiv())
|
||||||
|
return dr.getText().getDiv();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return wrapped.getResourceType().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
List<PropertyWrapper> list = new ArrayList<PropertyWrapper>();
|
||||||
|
if (wrapped.children() != null) {
|
||||||
|
for (Property c : wrapped.children())
|
||||||
|
list.add(new PropertyWrapperDirect(renderer, c));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describe(XhtmlNode x) {
|
||||||
|
if (wrapped instanceof CanonicalResource) {
|
||||||
|
x.tx(((CanonicalResource) wrapped).present());
|
||||||
|
} else if (wrapped instanceof Patient) {
|
||||||
|
new PatientRenderer(getRenderer().getContext()).describe(x, (Patient) wrapped);
|
||||||
|
} else if (wrapped instanceof Encounter) {
|
||||||
|
new EncounterRenderer(getRenderer().getContext()).describe(x, (Encounter) wrapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
|
import org.hl7.fhir.r5.elementmodel.XmlParser;
|
||||||
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
|
import org.hl7.fhir.r5.model.Base;
|
||||||
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl;
|
||||||
|
import org.hl7.fhir.r5.utils.NarrativeGenerator;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
public class ElementWrappers {
|
||||||
|
|
||||||
|
public static class BaseWrapperMetaElement extends WrapperBaseImpl implements BaseWrapper {
|
||||||
|
private Element element;
|
||||||
|
private String type;
|
||||||
|
private StructureDefinition structure;
|
||||||
|
private ElementDefinition definition;
|
||||||
|
private List<ElementDefinition> children;
|
||||||
|
private List<PropertyWrapper> list;
|
||||||
|
|
||||||
|
public BaseWrapperMetaElement(ResourceRenderer renderer, Element element, String type, StructureDefinition structure, ElementDefinition definition) {
|
||||||
|
super(renderer);
|
||||||
|
this.element = element;
|
||||||
|
this.type = type;
|
||||||
|
this.structure = structure;
|
||||||
|
this.definition = definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException {
|
||||||
|
if (type == null || type.equals("Resource") || type.equals("BackboneElement") || type.equals("Element"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (element.hasElementProperty())
|
||||||
|
return null;
|
||||||
|
ByteArrayOutputStream xml = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
new XmlParser(renderer.getContext().getWorker()).compose(element, xml, OutputStyle.PRETTY, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new FHIRException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return renderer.parseType(xml.toString(), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
if (list == null) {
|
||||||
|
children = renderer.getContext().getProfileUtilities().getChildList(structure, definition);
|
||||||
|
list = new ArrayList<PropertyWrapper>();
|
||||||
|
for (ElementDefinition child : children) {
|
||||||
|
List<Element> elements = new ArrayList<Element>();
|
||||||
|
String name = tail(child.getPath());
|
||||||
|
if (name.endsWith("[x]"))
|
||||||
|
element.getNamedChildrenWithWildcard(name, elements);
|
||||||
|
else
|
||||||
|
element.getNamedChildren(name, elements);
|
||||||
|
list.add(new PropertyWrapperMetaElement(renderer, structure, child, elements));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyWrapper getChildByName(String name) {
|
||||||
|
for (PropertyWrapper p : children())
|
||||||
|
if (p.getName().equals(name))
|
||||||
|
return p;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceWrapperMetaElement extends WrapperBaseImpl implements ResourceWrapper {
|
||||||
|
private Element wrapped;
|
||||||
|
private List<ResourceWrapper> list;
|
||||||
|
private List<PropertyWrapper> list2;
|
||||||
|
private StructureDefinition definition;
|
||||||
|
public ResourceWrapperMetaElement(ResourceRenderer renderer, Element wrapped) {
|
||||||
|
super(renderer);
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
this.definition = wrapped.getProperty().getStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ResourceWrapper> getContained() {
|
||||||
|
if (list == null) {
|
||||||
|
List<Element> children = wrapped.getChildrenByName("contained");
|
||||||
|
list = new ArrayList<ResourceWrapper>();
|
||||||
|
for (Element e : children) {
|
||||||
|
list.add(new ResourceWrapperMetaElement(renderer, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return wrapped.getNamedChildValue("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException {
|
||||||
|
Element txt = wrapped.getNamedChild("text");
|
||||||
|
if (txt == null)
|
||||||
|
return null;
|
||||||
|
Element div = txt.getNamedChild("div");
|
||||||
|
if (div == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return div.getXhtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return wrapped.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyWrapper> children() {
|
||||||
|
if (list2 == null) {
|
||||||
|
List<ElementDefinition> children = renderer.getContext().getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0));
|
||||||
|
list2 = new ArrayList<PropertyWrapper>();
|
||||||
|
for (ElementDefinition child : children) {
|
||||||
|
List<Element> elements = new ArrayList<Element>();
|
||||||
|
if (child.getPath().endsWith("[x]"))
|
||||||
|
wrapped.getNamedChildrenWithWildcard(tail(child.getPath()), elements);
|
||||||
|
else
|
||||||
|
wrapped.getNamedChildren(tail(child.getPath()), elements);
|
||||||
|
list2.add(new PropertyWrapperMetaElement(renderer, definition, child, elements));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describe(XhtmlNode x) {
|
||||||
|
if (wrapped.hasChild("title") && wrapped.getChildValue("title") != null) {
|
||||||
|
x.tx(wrapped.getChildValue("title"));
|
||||||
|
} else if (wrapped.hasChild("name") && wrapped.getChildValue("name") != null) {
|
||||||
|
x.tx(wrapped.getChildValue("name"));
|
||||||
|
} else {
|
||||||
|
x.tx("?ngen-1?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper {
|
||||||
|
|
||||||
|
private StructureDefinition structure;
|
||||||
|
private ElementDefinition definition;
|
||||||
|
private List<Element> values;
|
||||||
|
private List<BaseWrapper> list;
|
||||||
|
|
||||||
|
public PropertyWrapperMetaElement(ResourceRenderer renderer, StructureDefinition structure, ElementDefinition definition, List<Element> values) {
|
||||||
|
super(renderer);
|
||||||
|
this.structure = structure;
|
||||||
|
this.definition = definition;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return tail(definition.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasValues() {
|
||||||
|
return values.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaseWrapper> getValues() {
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<BaseWrapper>();
|
||||||
|
for (Element e : values)
|
||||||
|
list.add(new BaseWrapperMetaElement(renderer, e, e.fhirType(), structure, definition));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTypeCode() {
|
||||||
|
return definition.typeSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefinition() {
|
||||||
|
return definition.getDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinCardinality() {
|
||||||
|
return definition.getMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxCardinality() {
|
||||||
|
return "*".equals(definition.getMax()) ? Integer.MAX_VALUE : Integer.valueOf(definition.getMax());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructureDefinition getStructure() {
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseWrapper value() {
|
||||||
|
if (getValues().size() != 1)
|
||||||
|
throw new Error("Access single value, but value count is "+getValues().size());
|
||||||
|
return getValues().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.IReferenceResolver;
|
||||||
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
|
||||||
|
public class RenderingContext {
|
||||||
|
|
||||||
|
public enum ResourceRendererMode{
|
||||||
|
RESOURCE, IG
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IWorkerContext worker;
|
||||||
|
protected MarkDownProcessor markdown;
|
||||||
|
protected String lang;
|
||||||
|
protected String prefix;
|
||||||
|
protected ValidationOptions terminologyServiceOptions;
|
||||||
|
protected ProfileUtilities profileUtilities;
|
||||||
|
private boolean canonicalUrlsAsLinks;
|
||||||
|
protected ResourceRendererMode mode;
|
||||||
|
private IReferenceResolver resolver;
|
||||||
|
private int headerLevelContext;
|
||||||
|
private String tooCostlyNoteEmpty;
|
||||||
|
private String tooCostlyNoteNotEmpty;
|
||||||
|
private String tooCostlyNoteEmptyDependent;
|
||||||
|
private String tooCostlyNoteNotEmptyDependent;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param context - access to all related resources that might be needed
|
||||||
|
* @param markdown - appropriate markdown processing engine
|
||||||
|
* @param terminologyServiceOptions - options to use when looking up codes
|
||||||
|
* @param prefix - path to FHIR specification
|
||||||
|
* @param lang - langauage to render in
|
||||||
|
*/
|
||||||
|
public RenderingContext(IWorkerContext worker, MarkDownProcessor markdown, ValidationOptions terminologyServiceOptions, String prefix, String lang, ResourceRendererMode mode) {
|
||||||
|
super();
|
||||||
|
this.worker = worker;
|
||||||
|
this.markdown = markdown;
|
||||||
|
this.lang = lang;
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.mode = mode;
|
||||||
|
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||||
|
profileUtilities = new ProfileUtilities(worker, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkerContext getContext() {
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- 2. Markdown support -------------------------------------------------------
|
||||||
|
|
||||||
|
public ProfileUtilities getProfileUtilities() {
|
||||||
|
return profileUtilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkerContext getWorker() {
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCanonicalUrlsAsLinks() {
|
||||||
|
return canonicalUrlsAsLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCanonicalUrlsAsLinks(boolean canonicalUrlsAsLinks) {
|
||||||
|
this.canonicalUrlsAsLinks = canonicalUrlsAsLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkDownProcessor getMarkdown() {
|
||||||
|
return markdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLang() {
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationOptions getTerminologyServiceOptions() {
|
||||||
|
return terminologyServiceOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getTooCostlyNoteEmpty() {
|
||||||
|
return tooCostlyNoteEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTooCostlyNoteEmpty(String tooCostlyNoteEmpty) {
|
||||||
|
this.tooCostlyNoteEmpty = tooCostlyNoteEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooCostlyNoteNotEmpty() {
|
||||||
|
return tooCostlyNoteNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTooCostlyNoteNotEmpty(String tooCostlyNoteNotEmpty) {
|
||||||
|
this.tooCostlyNoteNotEmpty = tooCostlyNoteNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooCostlyNoteEmptyDependent() {
|
||||||
|
return tooCostlyNoteEmptyDependent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTooCostlyNoteEmptyDependent(String tooCostlyNoteEmptyDependent) {
|
||||||
|
this.tooCostlyNoteEmptyDependent = tooCostlyNoteEmptyDependent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooCostlyNoteNotEmptyDependent() {
|
||||||
|
return tooCostlyNoteNotEmptyDependent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTooCostlyNoteNotEmptyDependent(String tooCostlyNoteNotEmptyDependent) {
|
||||||
|
this.tooCostlyNoteNotEmptyDependent = tooCostlyNoteNotEmptyDependent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeaderLevelContext() {
|
||||||
|
return headerLevelContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderLevelContext(int headerLevelContext) {
|
||||||
|
this.headerLevelContext = headerLevelContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReferenceResolver getResolver() {
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResolver(IReferenceResolver resolver) {
|
||||||
|
this.resolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTerminologyServiceOptions(ValidationOptions terminologyServiceOptions) {
|
||||||
|
this.terminologyServiceOptions = terminologyServiceOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
package org.hl7.fhir.r5.renderers.utils;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.model.Bundle;
|
||||||
|
import org.hl7.fhir.r5.model.DomainResource;
|
||||||
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
public class Resolver {
|
||||||
|
|
||||||
|
public interface IReferenceResolver {
|
||||||
|
ResourceWithReference resolve(String url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceContext {
|
||||||
|
Bundle bundleResource;
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element bundleElement;
|
||||||
|
|
||||||
|
DomainResource resourceResource;
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element resourceElement;
|
||||||
|
|
||||||
|
public ResourceContext(Bundle bundle, DomainResource dr) {
|
||||||
|
super();
|
||||||
|
this.bundleResource = bundle;
|
||||||
|
this.resourceResource = dr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContext(org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||||
|
this.bundleElement = bundle;
|
||||||
|
this.resourceElement = dr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContext(Object bundle, Element doc) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bundle getBundleResource() {
|
||||||
|
return bundleResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||||
|
return bundleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DomainResource getResourceResource() {
|
||||||
|
return resourceResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.hl7.fhir.r5.elementmodel.Element getResourceElement() {
|
||||||
|
return resourceElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BundleEntryComponent resolve(String value) {
|
||||||
|
if (value.startsWith("#")) {
|
||||||
|
if (resourceResource != null) {
|
||||||
|
for (Resource r : resourceResource.getContained()) {
|
||||||
|
if (r.getId().equals(value.substring(1))) {
|
||||||
|
BundleEntryComponent be = new BundleEntryComponent();
|
||||||
|
be.setResource(r);
|
||||||
|
return be;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (bundleResource != null) {
|
||||||
|
for (BundleEntryComponent be : bundleResource.getEntry()) {
|
||||||
|
if (be.getFullUrl().equals(value))
|
||||||
|
return be;
|
||||||
|
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||||
|
return be;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value) {
|
||||||
|
if (value.startsWith("#")) {
|
||||||
|
if (resourceElement != null) {
|
||||||
|
for (org.hl7.fhir.r5.elementmodel.Element r : resourceElement.getChildrenByName("contained")) {
|
||||||
|
if (r.getChildValue("id").equals(value.substring(1)))
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (bundleElement != null) {
|
||||||
|
for (org.hl7.fhir.r5.elementmodel.Element be : bundleElement.getChildren("entry")) {
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||||
|
if (value.equals(be.getChildValue("fullUrl")))
|
||||||
|
return be;
|
||||||
|
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||||
|
return be;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceWithReference {
|
||||||
|
|
||||||
|
private String reference;
|
||||||
|
private ResourceWrapper resource;
|
||||||
|
|
||||||
|
public ResourceWithReference(String reference, ResourceWrapper resource) {
|
||||||
|
this.reference = reference;
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReference() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceWrapper getResource() {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -22,39 +22,13 @@ package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||||
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
/*
|
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -65,7 +39,6 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
|
@ -184,18 +157,12 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemRenderer;
|
import org.hl7.fhir.r5.renderers.CodeSystemRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
import org.hl7.fhir.r5.renderers.ConceptMapRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
import org.hl7.fhir.r5.renderers.TerminologyRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.ConceptMapRenderer;
|
import org.hl7.fhir.r5.renderers.ValueSetRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer;
|
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer.ConceptMapRenderInstructions;
|
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer.TerminologyRendererMode;
|
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetRenderer;
|
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||||
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument;
|
||||||
import org.hl7.fhir.r5.utils.NarrativeGenerator.ResourceContext;
|
|
||||||
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
|
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
|
||||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||||
|
@ -222,75 +189,6 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException ;
|
Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResourceContext {
|
|
||||||
Bundle bundleResource;
|
|
||||||
org.hl7.fhir.r5.elementmodel.Element bundleElement;
|
|
||||||
|
|
||||||
DomainResource resourceResource;
|
|
||||||
org.hl7.fhir.r5.elementmodel.Element resourceElement;
|
|
||||||
|
|
||||||
public ResourceContext(Bundle bundle, DomainResource dr) {
|
|
||||||
super();
|
|
||||||
this.bundleResource = bundle;
|
|
||||||
this.resourceResource = dr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceContext(org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
|
||||||
this.bundleElement = bundle;
|
|
||||||
this.resourceElement = dr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceContext(Object bundle, Element doc) {
|
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
public BundleEntryComponent resolve(String value) {
|
|
||||||
if (value.startsWith("#")) {
|
|
||||||
if (resourceResource != null) {
|
|
||||||
for (Resource r : resourceResource.getContained()) {
|
|
||||||
if (r.getId().equals(value.substring(1))) {
|
|
||||||
BundleEntryComponent be = new BundleEntryComponent();
|
|
||||||
be.setResource(r);
|
|
||||||
return be;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (bundleResource != null) {
|
|
||||||
for (BundleEntryComponent be : bundleResource.getEntry()) {
|
|
||||||
if (be.getFullUrl().equals(value))
|
|
||||||
return be;
|
|
||||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
|
||||||
return be;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value) {
|
|
||||||
if (value.startsWith("#")) {
|
|
||||||
if (resourceElement != null) {
|
|
||||||
for (org.hl7.fhir.r5.elementmodel.Element r : resourceElement.getChildrenByName("contained")) {
|
|
||||||
if (r.getChildValue("id").equals(value.substring(1)))
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (bundleElement != null) {
|
|
||||||
for (org.hl7.fhir.r5.elementmodel.Element be : bundleElement.getChildren("entry")) {
|
|
||||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
|
||||||
if (value.equals(be.getChildValue("fullUrl")))
|
|
||||||
return be;
|
|
||||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
|
||||||
return be;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IReferenceResolver {
|
public interface IReferenceResolver {
|
||||||
ResourceWithReference resolve(String url);
|
ResourceWithReference resolve(String url);
|
||||||
}
|
}
|
||||||
|
@ -1225,12 +1123,12 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
x.para().b().tx("Generated Narrative"+(showCodeDetails ? " with Details" : ""));
|
x.para().b().tx("Generated Narrative"+(showCodeDetails ? " with Details" : ""));
|
||||||
try {
|
try {
|
||||||
generateByProfile(rc.resourceResource, profile, rc.resourceResource, profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), rc.resourceResource.getResourceType().toString()), x, rc.resourceResource.getResourceType().toString(), showCodeDetails, rc);
|
generateByProfile(rc.getResourceResource(), profile, rc.getResourceResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), rc.getResourceResource().getResourceType().toString()), x, rc.getResourceResource().getResourceType().toString(), showCodeDetails, rc);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||||
}
|
}
|
||||||
inject(rc.resourceResource, x, NarrativeStatus.GENERATED);
|
inject(rc.getResourceResource(), x, NarrativeStatus.GENERATED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1557,7 +1455,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
renderContactPoint(c, x);
|
renderContactPoint(c, x);
|
||||||
}
|
}
|
||||||
} else if (e instanceof UriType) {
|
} else if (e instanceof UriType) {
|
||||||
renderUri((UriType) e, x, defn.getPath(), rc != null && rc.resourceResource != null ? rc.resourceResource.getId() : null);
|
renderUri((UriType) e, x, defn.getPath(), rc != null && rc.getResourceResource() != null ? rc.getResourceResource().getId() : null);
|
||||||
} else if (e instanceof Timing) {
|
} else if (e instanceof Timing) {
|
||||||
renderTiming((Timing) e, x);
|
renderTiming((Timing) e, x);
|
||||||
} else if (e instanceof Range) {
|
} else if (e instanceof Range) {
|
||||||
|
@ -2420,8 +2318,8 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
|
|
||||||
public boolean generate(ResourceContext rcontext, ConceptMap cm) throws FHIRFormatError, DefinitionException, IOException {
|
public boolean generate(ResourceContext rcontext, ConceptMap cm) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
ConceptMapRenderer renderer = new ConceptMapRenderer(TerminologyRendererMode.RESOURCE, context, markdown, prefix, null);
|
ConceptMapRenderer renderer = new ConceptMapRenderer(new RenderingContext(context, markdown, terminologyServiceOptions, prefix, null, ResourceRendererMode.RESOURCE), rcontext);
|
||||||
boolean res = renderer.generate(rcontext, cm, x);
|
boolean res = renderer.render(x, cm);
|
||||||
inject(cm, x, NarrativeStatus.GENERATED);
|
inject(cm, x, NarrativeStatus.GENERATED);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -2545,11 +2443,11 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
*/
|
*/
|
||||||
public boolean generate(ResourceContext rcontext, CodeSystem cs, boolean header, String lang) throws FHIRFormatError, DefinitionException, IOException {
|
public boolean generate(ResourceContext rcontext, CodeSystem cs, boolean header, String lang) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
CodeSystemRenderer renderer = new CodeSystemRenderer(TerminologyRendererMode.RESOURCE, context, markdown, prefix, lang);
|
CodeSystemRenderer renderer = new CodeSystemRenderer(new RenderingContext(context, markdown, terminologyServiceOptions, prefix, lang, ResourceRendererMode.RESOURCE), rcontext);
|
||||||
renderer.getCodeSystemPropList().addAll(getCodeSystemPropList());
|
renderer.getCodeSystemPropList().addAll(getCodeSystemPropList());
|
||||||
renderer.setHeaderLevelContext(headerLevelContext);
|
renderer.getContext().setHeaderLevelContext(headerLevelContext);
|
||||||
renderer.setTerminologyServiceOptions(terminologyServiceOptions);
|
renderer.getContext().setTerminologyServiceOptions(terminologyServiceOptions);
|
||||||
boolean hasExtensions = renderer.generate(x, cs, header);
|
boolean hasExtensions = renderer.render(x, cs, header);
|
||||||
inject(cs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
inject(cs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2572,16 +2470,16 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
|
|
||||||
public void generate(ResourceContext rcontext, ValueSet vs, ValueSet src, boolean header) throws FHIRException, IOException {
|
public void generate(ResourceContext rcontext, ValueSet vs, ValueSet src, boolean header) throws FHIRException, IOException {
|
||||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
ValueSetRenderer renderer = new ValueSetRenderer(TerminologyRendererMode.RESOURCE, context, markdown, prefix, null);
|
ValueSetRenderer renderer = new ValueSetRenderer(new RenderingContext(context, markdown, terminologyServiceOptions, prefix, null, ResourceRendererMode.RESOURCE), rcontext);
|
||||||
renderer.setTooCostlyNoteEmpty(tooCostlyNoteEmpty);
|
renderer.getContext().setTooCostlyNoteEmpty(tooCostlyNoteEmpty);
|
||||||
renderer.setTooCostlyNoteNotEmpty(tooCostlyNoteNotEmpty);
|
renderer.getContext().setTooCostlyNoteNotEmpty(tooCostlyNoteNotEmpty);
|
||||||
renderer.setTooCostlyNoteEmptyDependent(tooCostlyNoteEmptyDependent);
|
renderer.getContext().setTooCostlyNoteEmptyDependent(tooCostlyNoteEmptyDependent);
|
||||||
renderer.setTooCostlyNoteNotEmptyDependent(tooCostlyNoteNotEmptyDependent);
|
renderer.getContext().setTooCostlyNoteNotEmptyDependent(tooCostlyNoteNotEmptyDependent);
|
||||||
renderer.setNoSlowLookup(noSlowLookup);
|
renderer.setNoSlowLookup(noSlowLookup);
|
||||||
renderer.setHeaderLevelContext(headerLevelContext);
|
renderer.getContext().setHeaderLevelContext(headerLevelContext);
|
||||||
renderer.setTerminologyServiceOptions(terminologyServiceOptions);
|
renderer.getContext().setTerminologyServiceOptions(terminologyServiceOptions);
|
||||||
|
|
||||||
boolean hasExtensions = renderer.render(rcontext, x, vs, src, header);
|
boolean hasExtensions = renderer.render(x, vs, header);
|
||||||
inject(vs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
inject(vs, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||||
import org.hl7.fhir.r5.model.UriType;
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyRenderer;
|
import org.hl7.fhir.r5.renderers.TerminologyRenderer;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||||
|
|
|
@ -518,8 +518,8 @@ public class SnapShotGenerationTests {
|
||||||
pu.setThrowException(false);
|
pu.setThrowException(false);
|
||||||
pu.setDebug(test.isDebug());
|
pu.setDebug(test.isDebug());
|
||||||
pu.setIds(test.getSource(), false);
|
pu.setIds(test.getSource(), false);
|
||||||
if (!TestingUtilities.context().hasPackage("hl7.fhir.xver-extensions", "0.0.3")) {
|
if (!TestingUtilities.context().hasPackage("hl7.fhir.xver-extensions", "0.0.4")) {
|
||||||
NpmPackage npm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.xver-extensions", "0.0.3");
|
NpmPackage npm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.xver-extensions", "0.0.4");
|
||||||
TestingUtilities.context().loadFromPackage(npm, new TestLoader(new String[]{"StructureDefinition"}), new String[]{"StructureDefinition"});
|
TestingUtilities.context().loadFromPackage(npm, new TestLoader(new String[]{"StructureDefinition"}), new String[]{"StructureDefinition"});
|
||||||
}
|
}
|
||||||
pu.setXver(new XVerExtensionManager(TestingUtilities.context()));
|
pu.setXver(new XVerExtensionManager(TestingUtilities.context()));
|
||||||
|
|
|
@ -342,7 +342,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion(), new PackageVersion(src));
|
context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion(), new PackageVersion(src));
|
||||||
context.setAllowLoadingDuplicates(true); // because of Forge
|
context.setAllowLoadingDuplicates(true); // because of Forge
|
||||||
context.setExpansionProfile(makeExpProfile());
|
context.setExpansionProfile(makeExpProfile());
|
||||||
NpmPackage npm = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.3");
|
NpmPackage npm = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.4");
|
||||||
context.loadFromPackage(npm, null);
|
context.loadFromPackage(npm, null);
|
||||||
grabNatives(source, "http://hl7.org/fhir");
|
grabNatives(source, "http://hl7.org/fhir");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue