Add support for using Liquid on plain JSON directly and add support for markdownify filter

This commit is contained in:
Grahame Grieve 2024-12-02 06:51:16 +03:00
parent 1cdb7ea695
commit 0ba7d8434c
3 changed files with 121 additions and 3 deletions

View File

@ -331,7 +331,7 @@ public class TerminologyClientManager {
private String host() throws MalformedURLException {
URL url = new URL(getMasterClient().getAddress());
if (url.getPort() != 0) {
if (url.getPort() > 0) {
return url.getHost()+":"+url.getPort();
} else {
return url.getHost();

View File

@ -0,0 +1,87 @@
package org.hl7.fhir.r5.utils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonElement;
// this class exists to allow the Liquid Engine to be used against raw JSON
public class BaseJsonWrapper extends Base {
private static final long serialVersionUID = 1L;
private JsonElement j;
public BaseJsonWrapper(JsonElement j) {
super();
this.j = j;
}
@Override
public String fhirType() {
switch (j.type()) {
case BOOLEAN: return "boolean";
case NUMBER: return "decimal";
case OBJECT: return "Object";
case STRING: return "string";
default:
throw new Error("Shouldn't get here");
}
}
@Override
public String getIdBase() {
if (j.isJsonObject()) {
return j.asJsonObject().asString("id");
} else {
return null;
}
}
@Override
public void setIdBase(String value) {
throw new Error("BaseJsonWrapper is read only");
}
@Override
public Base copy() {
throw new Error("BaseJsonWrapper is read only");
}
@Override
public FhirPublication getFHIRPublicationVersion() {
return FhirPublication.R5;
}
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
if (j.isJsonObject() && j.asJsonObject().has(name)) {
JsonElement e = j.asJsonObject().get(name);
if (e.isJsonArray()) {
JsonArray a = e.asJsonArray();
Base[] l = new Base[a.size()];
for (int i = 0; i < a.size(); i++) {
l[i] = new BaseJsonWrapper(a.get(i));
}
return l;
} else {
Base[] l = new Base[1];
l[0] = new BaseJsonWrapper(e);
return l;
}
} else {
return super.getProperty(hash, name, checkValid);
}
}
@Override
public String toString() {
if (j.isJsonPrimitive()) {
return j.asString();
} else {
return super.toString();
}
}
}

View File

@ -49,7 +49,9 @@ import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Tuple;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -68,7 +70,8 @@ public class LiquidEngine implements IEvaluationContext {
private FHIRPathEngine engine;
private ILiquidEngineIncludeResolver includeResolver;
private ILiquidRenderingSupport renderingSupport;
private MarkDownProcessor processor = new MarkDownProcessor(Dialect.COMMON_MARK);
private class LiquidEngineContext {
private Object externalContext;
private Map<String, Base> loopVars = new HashMap<>();
@ -162,12 +165,24 @@ public class LiquidEngine implements IEvaluationContext {
}
private enum LiquidFilter {
PREPEND;
PREPEND,
MARKDOWNIFY,
UPCASE,
DOWNCASE;
public static LiquidFilter fromCode(String code) {
if ("prepend".equals(code)) {
return PREPEND;
}
if ("markdownify".equals(code)) {
return MARKDOWNIFY;
}
if ("upcase".equals(code)) {
return UPCASE;
}
if ("downcase".equals(code)) {
return DOWNCASE;
}
return null;
}
}
@ -221,12 +236,25 @@ public class LiquidEngine implements IEvaluationContext {
} else switch (i.filter) {
case PREPEND:
t = stmtToString(ctxt, engine.evaluate(ctxt, resource, resource, resource, i.expression)) + t;
break;
case MARKDOWNIFY:
t = processMarkdown(t);
break;
case UPCASE:
t = t.toUpperCase();
break;
case DOWNCASE:
t = t.toLowerCase();
break;
}
}
b.append(t);
}
private String processMarkdown(String t) {
return processor.process(t, "liquid");
}
private String stmtToString(LiquidEngineContext ctxt, List<Base> items) {
StringBuilder b = new StringBuilder();
boolean first = true;
@ -489,6 +517,9 @@ public class LiquidEngine implements IEvaluationContext {
public LiquidParser(String source) {
this.source = source;
if (source == null) {
throw new FHIRException("No Liquid source to parse");
}
cursor = 0;
}