liquid fixes to FHIRPath
This commit is contained in:
parent
e2dff7d118
commit
2f0a45046e
|
@ -76,6 +76,7 @@ public class FHIRLexer {
|
|||
private SourceLocation currentStartLocation;
|
||||
private int id;
|
||||
private String name;
|
||||
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
||||
|
||||
public FHIRLexer(String source, String name) throws FHIRLexerException {
|
||||
this.source = source == null ? "" : source;
|
||||
|
@ -272,6 +273,12 @@ public class FHIRLexer {
|
|||
throw error("Unterminated string");
|
||||
cursor++;
|
||||
current = "`"+source.substring(currentStart+1, cursor-1)+"`";
|
||||
} else if (ch == '|' && liquidMode) {
|
||||
cursor++;
|
||||
ch = source.charAt(cursor);
|
||||
if (ch == '|')
|
||||
cursor++;
|
||||
current = source.substring(currentStart, cursor);
|
||||
} else if (ch == '@'){
|
||||
int start = cursor;
|
||||
cursor++;
|
||||
|
@ -520,5 +527,11 @@ public class FHIRLexer {
|
|||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
public boolean isLiquidMode() {
|
||||
return liquidMode;
|
||||
}
|
||||
public void setLiquidMode(boolean liquidMode) {
|
||||
this.liquidMode = liquidMode;
|
||||
}
|
||||
|
||||
}
|
|
@ -262,6 +262,7 @@ public class FHIRPathEngine {
|
|||
private String location; // for error messages
|
||||
private boolean allowPolymorphicNames;
|
||||
private boolean doImplicitStringConversion;
|
||||
private boolean liquidMode; // in liquid mode, || terminates the expression and hands the parser back to the host
|
||||
|
||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||
// the application can implement them by providing a constant resolver
|
||||
|
@ -6034,5 +6035,13 @@ public class FHIRPathEngine {
|
|||
this.allowPolymorphicNames = allowPolymorphicNames;
|
||||
}
|
||||
|
||||
public boolean isLiquidMode() {
|
||||
return liquidMode;
|
||||
}
|
||||
|
||||
public void setLiquidMode(boolean liquidMode) {
|
||||
this.liquidMode = liquidMode;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ public class LiquidEngine implements IEvaluationContext {
|
|||
this.externalHostServices = hostServices;
|
||||
engine = new FHIRPathEngine(context);
|
||||
engine.setHostServices(this);
|
||||
engine.setLiquidMode(true);
|
||||
}
|
||||
|
||||
public ILiquidEngineIncludeResolver getIncludeResolver() {
|
||||
|
@ -152,22 +153,82 @@ public class LiquidEngine implements IEvaluationContext {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private enum LiquidFilter {
|
||||
PREPEND;
|
||||
|
||||
public static LiquidFilter fromCode(String code) {
|
||||
if ("prepend".equals(code)) {
|
||||
return PREPEND;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class LiquidExpressionNode {
|
||||
private LiquidFilter filter; // null at root
|
||||
private ExpressionNode expression; // null for some filters
|
||||
public LiquidExpressionNode(LiquidFilter filter, ExpressionNode expression) {
|
||||
super();
|
||||
this.filter = filter;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LiquidStatement extends LiquidNode {
|
||||
private String statement;
|
||||
private ExpressionNode compiled;
|
||||
private List<LiquidExpressionNode> compiled = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void evaluate(StringBuilder b, Base resource, LiquidEngineContext ctxt) throws FHIRException {
|
||||
if (compiled == null)
|
||||
compiled = engine.parse(statement);
|
||||
List<Base> items = engine.evaluate(ctxt, resource, resource, resource, compiled);
|
||||
if (compiled.size() == 0) {
|
||||
FHIRLexer lexer = new FHIRLexer(statement, "liquid statement");
|
||||
lexer.setLiquidMode(true);
|
||||
compiled.add(new LiquidExpressionNode(null, engine.parse(lexer)));
|
||||
while (!lexer.done()) {
|
||||
if (lexer.getCurrent().equals("||")) {
|
||||
lexer.next();
|
||||
String f = lexer.getCurrent();
|
||||
LiquidFilter filter = LiquidFilter.fromCode(f);
|
||||
if (filter == null) {
|
||||
lexer.error("Unknown Liquid filter '"+f+"'");
|
||||
}
|
||||
lexer.next();
|
||||
if (!lexer.done() && lexer.getCurrent().equals(":")) {
|
||||
lexer.next();
|
||||
compiled.add(new LiquidExpressionNode(filter, engine.parse(lexer)));
|
||||
} else {
|
||||
compiled.add(new LiquidExpressionNode(filter, null));
|
||||
}
|
||||
} else {
|
||||
lexer.error("Unexpected syntax parsing liquid statement");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String t = null;
|
||||
for (LiquidExpressionNode i : compiled) {
|
||||
if (i.filter == null) { // first
|
||||
t = stmtToString(ctxt, engine.evaluate(ctxt, resource, resource, resource, i.expression));
|
||||
} else switch (i.filter) {
|
||||
case PREPEND:
|
||||
t = stmtToString(ctxt, engine.evaluate(ctxt, resource, resource, resource, i.expression)) + t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
b.append(t);
|
||||
}
|
||||
|
||||
private String stmtToString(LiquidEngineContext ctxt, List<Base> items) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Base i : items) {
|
||||
if (first) first = false; else b.append(", ");
|
||||
String s = renderingSupport != null ? renderingSupport.renderForLiquid(ctxt.externalContext, i) : null;
|
||||
b.append(s != null ? s : engine.convertToString(i));
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue