i18n framework for HTML generation in renderers - step #1
This commit is contained in:
parent
473b63dbff
commit
1b6137967f
|
@ -7,6 +7,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
||||||
|
@ -138,23 +139,29 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String sentenceForContent(CodeSystemContentMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case COMPLETE: return "This code system <param name='cs'/> defines the following code<if test='code-count != 1'>s</if>:";
|
||||||
|
case EXAMPLE: return "This code system <param name='cs'/> provides some example code<if test='code-count != 1'>s</if>:";
|
||||||
|
case FRAGMENT: return "This code system <param name='cs'/> provides a fragment that includes following code<if test='code-count != 1'>s</if>:";
|
||||||
|
case NOTPRESENT: return "This code system <param name='cs'/> defines codes, but no codes are represented here";
|
||||||
|
case SUPPLEMENT: return "This code system <param name='cs'/> defines properties on the following code<if test='code-count != 1'>s</if>:";
|
||||||
|
}
|
||||||
|
throw new FHIRException("Unknown CodeSystemContentMode mode");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps, boolean props) throws FHIRFormatError, DefinitionException, IOException {
|
private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps, boolean props) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
if (props) {
|
if (props) {
|
||||||
x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Concepts", getContext().getLang()));
|
x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Concepts", getContext().getLang()));
|
||||||
}
|
}
|
||||||
XhtmlNode p = x.para();
|
XhtmlNode p = x.para();
|
||||||
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system "));
|
p.param("cs").code().tx(cs.getUrl());
|
||||||
p.code().tx(cs.getUrl());
|
p.paramValue("code-count", CodeSystemUtilities.countCodes(cs));
|
||||||
if (cs.getContent() == CodeSystemContentMode.COMPLETE)
|
p.sentenceForParams(sentenceForContent(cs.getContent()));
|
||||||
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines the following codes")+":");
|
if (cs.getContent() == CodeSystemContentMode.NOTPRESENT) {
|
||||||
else if (cs.getContent() == CodeSystemContentMode.EXAMPLE)
|
|
||||||
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines some example codes")+":");
|
|
||||||
else if (cs.getContent() == CodeSystemContentMode.FRAGMENT )
|
|
||||||
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines many codes, of which the following are a subset")+":");
|
|
||||||
else if (cs.getContent() == CodeSystemContentMode.NOTPRESENT ) {
|
|
||||||
p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines many codes, but they are not represented here"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
XhtmlNode t = x.table( "codes");
|
XhtmlNode t = x.table( "codes");
|
||||||
boolean definitions = false;
|
boolean definitions = false;
|
||||||
boolean commentS = false;
|
boolean commentS = false;
|
||||||
|
@ -198,7 +205,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
||||||
if (langs.size() > 0) {
|
if (langs.size() > 0) {
|
||||||
Collections.sort(langs);
|
Collections.sort(langs);
|
||||||
x.para().b().tx("Additional Language Displays");
|
x.para().b().tx("Additional Language Displays");
|
||||||
t = x.table( "codes");
|
t = x.table("codes");
|
||||||
XhtmlNode tr = t.tr();
|
XhtmlNode tr = t.tr();
|
||||||
tr.td().b().tx("Code");
|
tr.td().b().tx("Code");
|
||||||
for (String lang : langs)
|
for (String lang : langs)
|
||||||
|
|
|
@ -708,5 +708,17 @@ public class CodeSystemUtilities {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int countCodes(CodeSystem cs) {
|
||||||
|
return countCodes(cs.getConcept());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int countCodes(List<ConceptDefinitionComponent> concept) {
|
||||||
|
int t = concept.size();
|
||||||
|
for (ConceptDefinitionComponent cd : concept) {
|
||||||
|
t = t + (cd.hasConcept() ? countCodes(cd.getConcept()) : 0);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
@ -52,7 +53,6 @@ import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||||
public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
|
public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
|
||||||
private static final long serialVersionUID = -4362547161441436492L;
|
private static final long serialVersionUID = -4362547161441436492L;
|
||||||
|
|
||||||
|
|
||||||
public static class Location implements Serializable {
|
public static class Location implements Serializable {
|
||||||
private static final long serialVersionUID = -4079302502900219721L;
|
private static final long serialVersionUID = -4079302502900219721L;
|
||||||
private int line;
|
private int line;
|
||||||
|
@ -87,6 +87,8 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
|
||||||
private boolean notPretty;
|
private boolean notPretty;
|
||||||
private boolean seperated;
|
private boolean seperated;
|
||||||
private Boolean emptyExpanded;
|
private Boolean emptyExpanded;
|
||||||
|
private Map<String, XhtmlNode> namedParams;
|
||||||
|
private Map<String, String> namedParamValues;
|
||||||
|
|
||||||
public XhtmlNode() {
|
public XhtmlNode() {
|
||||||
super();
|
super();
|
||||||
|
@ -769,5 +771,70 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml {
|
||||||
return span("color: "+color, null);
|
return span("color: "+color, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XhtmlNode param(String name) {
|
||||||
|
XhtmlNode node = new XhtmlNode(NodeType.Element, "p"); // this node is dead will never appear anywhere, but we are in paragraph mode
|
||||||
|
if (namedParams == null) {
|
||||||
|
namedParams = new HashMap<>();
|
||||||
|
}
|
||||||
|
namedParams.put(name, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void paramValue(String name, String value) {
|
||||||
|
if (namedParamValues == null) {
|
||||||
|
namedParamValues = new HashMap<>();
|
||||||
|
}
|
||||||
|
namedParamValues.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paramValue(String name, int value) {
|
||||||
|
if (namedParamValues == null) {
|
||||||
|
namedParamValues = new HashMap<>();
|
||||||
|
}
|
||||||
|
namedParamValues.put(name, Integer.toString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sentenceForParams(String structure) throws FHIRException, IOException {
|
||||||
|
XhtmlNode script = new XhtmlParser().parseFragment("<div>"+structure+"</div>");
|
||||||
|
for (XhtmlNode n : script.getChildNodes()) {
|
||||||
|
if ("param".equals(n.getName())) {
|
||||||
|
XhtmlNode node = namedParams.get(n.getAttribute("name"));
|
||||||
|
if (node != null) {
|
||||||
|
this.getChildNodes().addAll(node.getChildNodes());
|
||||||
|
}
|
||||||
|
} else if ("if".equals(n.getName())) {
|
||||||
|
String test = n.getAttribute("test");
|
||||||
|
if (passesTest(test)) {
|
||||||
|
this.getChildNodes().addAll(n.getChildNodes());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.getChildNodes().add(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namedParams = null;
|
||||||
|
namedParamValues = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean passesTest(String test) {
|
||||||
|
String[] p = test.split("\\s+");
|
||||||
|
if (p.length != 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!namedParamValues.containsKey(p[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String pv = namedParamValues.get(p[0]);
|
||||||
|
switch (p[1]) {
|
||||||
|
case "=": return p[2].equalsIgnoreCase(pv);
|
||||||
|
case "!=": return !p[2].equalsIgnoreCase(pv);
|
||||||
|
case "<": return Utilities.isInteger(p[2]) && Utilities.isInteger(pv) && Integer.parseInt(pv) < Integer.parseInt(p[2]);
|
||||||
|
case "<=": return Utilities.isInteger(p[2]) && Utilities.isInteger(pv) && Integer.parseInt(pv) <= Integer.parseInt(p[2]);
|
||||||
|
case ">": return Utilities.isInteger(p[2]) && Utilities.isInteger(pv) && Integer.parseInt(pv) > Integer.parseInt(p[2]);
|
||||||
|
case ">=": return Utilities.isInteger(p[2]) && Utilities.isInteger(pv) && Integer.parseInt(pv) >= Integer.parseInt(p[2]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import java.io.ObjectOutputStream;
|
||||||
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.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
|
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||||
|
@ -150,5 +151,62 @@ public class XhtmlNodeTest {
|
||||||
Assertions.assertEquals(src.trim(), xml.trim());
|
Assertions.assertEquals(src.trim(), xml.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted1() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
x.para().tx("This is a paragraph");
|
||||||
|
Assertions.assertEquals("<div><p>This is a paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted2() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.tx("This is ");
|
||||||
|
p.tx("a paragraph");
|
||||||
|
Assertions.assertEquals("<div><p>This is a paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted3() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.tx("This is a ");
|
||||||
|
p.b().tx("long");
|
||||||
|
p.tx(" paragraph");
|
||||||
|
Assertions.assertEquals("<div><p>This is a <b>long</b> paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted4() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.param("long").b().tx("long");
|
||||||
|
p.sentenceForParams("This <b>is</b> a <param name='long'/> paragraph");
|
||||||
|
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted5() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.param("long").b().tx("long");
|
||||||
|
p.paramValue("count", "2");
|
||||||
|
p.sentenceForParams("This <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
|
||||||
|
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraphs</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComposeScripted6() throws IOException {
|
||||||
|
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.param("long").b().tx("long");
|
||||||
|
p.paramValue("count", "1");
|
||||||
|
p.sentenceForParams("This <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
|
||||||
|
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue