implement new FHIRPath functions

This commit is contained in:
Grahame Grieve 2020-06-03 06:52:47 +10:00
parent 08b59b89e2
commit 7ac1b1f0e0
4 changed files with 77 additions and 1 deletions

View File

@ -74,7 +74,7 @@ public class ExpressionNode {
Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse, AnyFalse, AllTrue, AnyTrue,
HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString, ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToTime, ToBoolean, ToInteger, ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo,
// R3 functions
Encode, Decode, Escape, Trim, Split, Join,
Encode, Decode, Escape, Unescape, Trim, Split, Join,
// Local extensions to FHIRPath
HtmlChecks, AliasAs, Alias;
@ -139,6 +139,7 @@ public class ExpressionNode {
if (name.equals("encode")) return Function.Encode;
if (name.equals("decode")) return Function.Decode;
if (name.equals("escape")) return Function.Escape;
if (name.equals("unescape")) return Function.Unescape;
if (name.equals("trim")) return Function.Trim;
if (name.equals("split")) return Function.Split;
if (name.equals("join")) return Function.Join;
@ -221,6 +222,7 @@ public class ExpressionNode {
case Encode : return "encode";
case Decode : return "decode";
case Escape : return "escape";
case Unescape : return "unescape";
case Trim : return "trim";
case Split : return "split";
case Join : return "join";

View File

@ -1151,6 +1151,7 @@ public class FHIRPathEngine {
case Encode: return checkParamCount(lexer, location, exp, 1);
case Decode: return checkParamCount(lexer, location, exp, 1);
case Escape: return checkParamCount(lexer, location, exp, 1);
case Unescape: return checkParamCount(lexer, location, exp, 1);
case Trim: return checkParamCount(lexer, location, exp, 0);
case Split: return checkParamCount(lexer, location, exp, 1);
case Join: return checkParamCount(lexer, location, exp, 1);
@ -2661,6 +2662,9 @@ public class FHIRPathEngine {
case Escape:
checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Unescape:
checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Trim:
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Split:
@ -2846,6 +2850,7 @@ public class FHIRPathEngine {
case Encode : return funcEncode(context, focus, exp);
case Decode : return funcDecode(context, focus, exp);
case Escape : return funcEscape(context, focus, exp);
case Unescape : return funcUnescape(context, focus, exp);
case Trim : return funcTrim(context, focus, exp);
case Split : return funcSplit(context, focus, exp);
case Join : return funcJoin(context, focus, exp);
@ -2958,6 +2963,23 @@ public class FHIRPathEngine {
return result;
}
private List<Base> funcUnescape(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String param = nl.get(0).primitiveValue();
List<Base> result = new ArrayList<Base>();
if (focus.size() == 1) {
String cnt = focus.get(0).primitiveValue();
if ("html".equals(param)) {
result.add(new StringType(Utilities.unescapeXml(cnt)));
} else if ("json".equals(param)) {
result.add(new StringType(Utilities.unescapeJson(cnt)));
}
}
return result;
}
private List<Base> funcTrim(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
List<Base> result = new ArrayList<Base>();
if (focus.size() == 1) {

View File

@ -213,6 +213,9 @@ public class FHIRPathTests {
Assertions.assertTrue(outcome.get(i).equalsDeep(q), String.format("Outcome %d: Value should be %s but was %s", i, v, outcome.get(i).toString()));
} else {
Assertions.assertTrue(outcome.get(i) instanceof PrimitiveType, String.format("Outcome %d: Value should be a primitive type but was %s", i, outcome.get(i).fhirType()));
if (!(v.equals(((PrimitiveType) outcome.get(i)).asStringValue()))) {
System.out.println(String.format("Outcome %d: Value should be %s but was %s for expression %s", i, v, outcome.get(i).toString(), expression));
}
Assertions.assertEquals(v, ((PrimitiveType) outcome.get(i)).asStringValue(), String.format("Outcome %d: Value should be %s but was %s for expression %s", i, v, outcome.get(i).toString(), expression));
}
}

View File

@ -509,6 +509,55 @@ public class Utilities {
return b.toString();
}
public static String unescapeJson(String json) throws FHIRException {
if (json == null)
return null;
StringBuilder b = new StringBuilder();
int i = 0;
while (i < json.length()) {
if (json.charAt(i) == '\\') {
i++;
char ch = json.charAt(i);
switch (ch) {
case '"':
b.append('b');
break;
case '\\':
b.append('\\');
break;
case '/':
b.append('/');
break;
case 'b':
b.append('\b');
break;
case 'f':
b.append('\f');
break;
case 'n':
b.append('\n');
break;
case 'r':
b.append('\r');
break;
case 't':
b.append('\t');
break;
case 'u':
String hex = json.substring(i+1, i+5);
b.append((char) Integer.parseInt(hex, 16));
break;
default:
throw new FHIRException("Unknown JSON escape \\"+ch);
}
} else
b.append(json.charAt(i));
i++;
}
return b.toString();
}
public static boolean isPlural(String word) {
word = word.toLowerCase();