Backport the defineVariable code to the R4 and R4B fhirpath implementations
This commit is contained in:
parent
0664e5601d
commit
d56404afd6
|
@ -50,7 +50,7 @@ public class ExpressionNode {
|
|||
Empty, Not, Exists, SubsetOf, SupersetOf, IsDistinct, Distinct, Count, Where, Select, All, Repeat, Aggregate,
|
||||
Item /* implicit from name[] */, As, Is, Single, First, Last, Tail, Skip, Take, Union, Combine, Intersect, Exclude,
|
||||
Iif, Upper, Lower, ToChars, IndexOf, Substring, StartsWith, EndsWith, Matches, MatchesFull, ReplaceMatches,
|
||||
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse,
|
||||
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, DefineVariable, Check, Today, Now, Resolve, Extension, AllFalse,
|
||||
AnyFalse, AllTrue, AnyTrue, HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString,
|
||||
ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToDate, ConvertsToTime, ToBoolean, ToInteger,
|
||||
ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo, Round, Sqrt, Abs, Ceiling, Exp, Floor, Ln, Log,
|
||||
|
@ -151,6 +151,8 @@ public class ExpressionNode {
|
|||
return Function.MemberOf;
|
||||
if (name.equals("trace"))
|
||||
return Function.Trace;
|
||||
if (name.equals("defineVariable"))
|
||||
return Function.DefineVariable;
|
||||
if (name.equals("check"))
|
||||
return Function.Check;
|
||||
if (name.equals("today"))
|
||||
|
@ -349,6 +351,8 @@ public class ExpressionNode {
|
|||
return "memberOf";
|
||||
case Trace:
|
||||
return "trace";
|
||||
case DefineVariable :
|
||||
return "defineVariable";
|
||||
case Check:
|
||||
return "check";
|
||||
case Today:
|
||||
|
|
|
@ -139,6 +139,7 @@ public class FHIRPathEngine {
|
|||
/**
|
||||
* A constant reference - e.g. a reference to a name that must be resolved in
|
||||
* context. The % will be removed from the constant name before this is invoked.
|
||||
* Variables created with defineVariable will not be processed by resolveConstant (or resolveConstantType)
|
||||
*
|
||||
* This will also be called if the host invokes the FluentPath engine with a
|
||||
* context of null
|
||||
|
@ -849,6 +850,7 @@ public class FHIRPathEngine {
|
|||
private Base thisItem;
|
||||
private List<Base> total;
|
||||
private int index;
|
||||
private Map<String, List<Base>> definedVariables;
|
||||
|
||||
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Base thisItem) {
|
||||
this.appInfo = appInfo;
|
||||
|
@ -887,6 +889,30 @@ public class FHIRPathEngine {
|
|||
index = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasDefinedVariable(String name) {
|
||||
return definedVariables != null && definedVariables.containsKey(name);
|
||||
}
|
||||
|
||||
public List<Base> getDefinedVariable(String name) {
|
||||
return definedVariables == null ? makeNull() : definedVariables.get(name);
|
||||
}
|
||||
|
||||
public void setDefinedVariable(String name, List<Base> value) {
|
||||
if (isSystemVariable(name))
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
|
||||
if (definedVariables == null) {
|
||||
definedVariables = new HashMap<String, List<Base>>();
|
||||
} else {
|
||||
if (definedVariables.containsKey(name)) {
|
||||
// Can't do this, so throw an error
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
definedVariables.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private class ExecutionTypeContext {
|
||||
|
@ -895,6 +921,7 @@ public class FHIRPathEngine {
|
|||
private TypeDetails context;
|
||||
private TypeDetails thisItem;
|
||||
private TypeDetails total;
|
||||
private Map<String, TypeDetails> definedVariables;
|
||||
|
||||
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
super();
|
||||
|
@ -913,6 +940,29 @@ public class FHIRPathEngine {
|
|||
return thisItem;
|
||||
}
|
||||
|
||||
public boolean hasDefinedVariable(String name) {
|
||||
return definedVariables != null && definedVariables.containsKey(name);
|
||||
}
|
||||
|
||||
public TypeDetails getDefinedVariable(String name) {
|
||||
return definedVariables == null ? null : definedVariables.get(name);
|
||||
}
|
||||
|
||||
public void setDefinedVariable(String name, TypeDetails value) {
|
||||
if (isSystemVariable(name))
|
||||
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
|
||||
if (definedVariables == null) {
|
||||
definedVariables = new HashMap<String, TypeDetails>();
|
||||
} else {
|
||||
if (definedVariables.containsKey(name)) {
|
||||
// Can't do this, so throw an error
|
||||
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
definedVariables.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
|
||||
|
@ -1314,6 +1364,8 @@ public class FHIRPathEngine {
|
|||
return checkParamCount(lexer, location, exp, 1);
|
||||
case Trace:
|
||||
return checkParamCount(lexer, location, exp, 1, 2);
|
||||
case DefineVariable:
|
||||
return checkParamCount(lexer, location, exp, 1, 2);
|
||||
case Check:
|
||||
return checkParamCount(lexer, location, exp, 2);
|
||||
case Today:
|
||||
|
@ -1419,9 +1471,10 @@ public class FHIRPathEngine {
|
|||
return false;
|
||||
}
|
||||
|
||||
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry)
|
||||
private List<Base> execute(ExecutionContext inContext, List<Base> focus, ExpressionNode exp, boolean atEntry)
|
||||
throws FHIRException {
|
||||
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
|
||||
ExecutionContext context = contextForParameter(inContext);
|
||||
List<Base> work = new ArrayList<Base>();
|
||||
switch (exp.getKind()) {
|
||||
case Unary:
|
||||
|
@ -1465,6 +1518,7 @@ public class FHIRPathEngine {
|
|||
ExpressionNode next = exp.getOpNext();
|
||||
ExpressionNode last = exp;
|
||||
while (next != null) {
|
||||
context = contextForParameter(inContext);
|
||||
List<Base> work2 = preOperate(work, last.getOperation(), exp);
|
||||
if (work2 != null) {
|
||||
work = work2;
|
||||
|
@ -1528,9 +1582,10 @@ public class FHIRPathEngine {
|
|||
return new TypeDetails(CollectionStatus.SINGLETON, exp.getName());
|
||||
}
|
||||
|
||||
private TypeDetails executeType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, boolean atEntry)
|
||||
private TypeDetails executeType(ExecutionTypeContext inContext, TypeDetails focus, ExpressionNode exp, boolean atEntry)
|
||||
throws PathEngineException, DefinitionException {
|
||||
TypeDetails result = new TypeDetails(null);
|
||||
ExecutionTypeContext context = contextForParameter(inContext);
|
||||
TypeDetails result = new TypeDetails(null);
|
||||
switch (exp.getKind()) {
|
||||
case Name:
|
||||
if (atEntry && exp.getName().equals("$this")) {
|
||||
|
@ -1574,6 +1629,7 @@ public class FHIRPathEngine {
|
|||
ExpressionNode next = exp.getOpNext();
|
||||
ExpressionNode last = exp;
|
||||
while (next != null) {
|
||||
context = contextForParameter(inContext);
|
||||
TypeDetails work;
|
||||
if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
|
||||
work = executeTypeName(context, focus, next, atEntry);
|
||||
|
@ -1598,6 +1654,10 @@ public class FHIRPathEngine {
|
|||
}
|
||||
FHIRConstant c = (FHIRConstant) constant;
|
||||
if (c.getValue().startsWith("%")) {
|
||||
String varName = c.getValue().substring(1);
|
||||
if (context.hasDefinedVariable(varName)) {
|
||||
return context.getDefinedVariable(varName);
|
||||
}
|
||||
return resolveConstant(context, c.getValue(), beforeContext, expr, explicitConstant);
|
||||
} else if (c.getValue().startsWith("@")) {
|
||||
return new ArrayList<Base>(Arrays.asList(processDateConstant(context.appInfo, c.getValue().substring(1), expr)));
|
||||
|
@ -1668,6 +1728,22 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
static boolean isSystemVariable(String name){
|
||||
if (name.equals("sct"))
|
||||
return true;
|
||||
if (name.equals("loinc"))
|
||||
return true;
|
||||
if (name.equals("ucum"))
|
||||
return true;
|
||||
if (name.equals("resource"))
|
||||
return true;
|
||||
if (name.equals("rootResource"))
|
||||
return true;
|
||||
if (name.equals("context"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Base> resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr, boolean explicitConstant)
|
||||
throws PathEngineException {
|
||||
if (s.equals("%sct")) {
|
||||
|
@ -3111,8 +3187,14 @@ public class FHIRPathEngine {
|
|||
} else if (s.startsWith("%`ext-")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
|
||||
} else if (hostServices == null) {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
|
||||
} else {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
return hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
|
||||
}
|
||||
}
|
||||
|
@ -3409,6 +3491,25 @@ public class FHIRPathEngine {
|
|||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
return focus;
|
||||
}
|
||||
case DefineVariable : {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.UNORDERED, TypeDetails.FP_String));
|
||||
// set the type of the variable
|
||||
// Actually evaluate the value of the first parameter (to get the name of the variable if possible)
|
||||
// and if have that, set it into the context
|
||||
ExpressionNode p = exp.getParameters().get(0);
|
||||
if (p.getKind() == Kind.Constant && p.getConstant() != null) {
|
||||
String varName = exp.getParameters().get(0).getConstant().primitiveValue();
|
||||
if (varName != null) {
|
||||
if (paramTypes.size() > 1)
|
||||
context.setDefinedVariable(varName, paramTypes.get(1));
|
||||
else
|
||||
context.setDefinedVariable(varName, focus);
|
||||
}
|
||||
} else {
|
||||
// this variable is not a constant, so we can't analyze what name it could have
|
||||
}
|
||||
return focus;
|
||||
}
|
||||
case Check: {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
|
||||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
|
@ -3592,7 +3693,7 @@ public class FHIRPathEngine {
|
|||
|| exp.getFunction() == Function.All || exp.getFunction() == Function.Select
|
||||
|| exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
|
||||
case 1:
|
||||
return exp.getFunction() == Function.Trace;
|
||||
return exp.getFunction() == Function.Trace || exp.getFunction() == Function.DefineVariable;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -3800,6 +3901,8 @@ public class FHIRPathEngine {
|
|||
return funcMemberOf(context, focus, exp);
|
||||
case Trace:
|
||||
return funcTrace(context, focus, exp);
|
||||
case DefineVariable:
|
||||
return funcDefineVariable(context, focus, exp);
|
||||
case Check:
|
||||
return funcCheck(context, focus, exp);
|
||||
case Today:
|
||||
|
@ -4532,11 +4635,50 @@ public class FHIRPathEngine {
|
|||
}
|
||||
|
||||
private ExecutionContext changeThis(ExecutionContext context, Base newThis) {
|
||||
return new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, newThis);
|
||||
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
|
||||
newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionContext contextForParameter(ExecutionContext context) {
|
||||
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.thisItem);
|
||||
newContext.total = context.total;
|
||||
newContext.index = context.index;
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
|
||||
return new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private List<Base> funcNow(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||
|
@ -5363,6 +5505,20 @@ public class FHIRPathEngine {
|
|||
return focus;
|
||||
}
|
||||
|
||||
private List<Base> funcDefineVariable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||
String name = nl.get(0).primitiveValue();
|
||||
List<Base> value;
|
||||
if (exp.getParameters().size() == 2) {
|
||||
value = execute(context, focus, exp.getParameters().get(1), true);
|
||||
} else {
|
||||
value = focus;
|
||||
}
|
||||
// stash the variable into the context
|
||||
context.setDefinedVariable(name, value);
|
||||
return focus;
|
||||
}
|
||||
|
||||
private List<Base> funcCheck(ExecutionContext context, List<Base> focus, ExpressionNode expr) throws FHIRException {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (!convertToBoolean(n1)) {
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ExpressionNode {
|
|||
Empty, Not, Exists, SubsetOf, SupersetOf, IsDistinct, Distinct, Count, Where, Select, All, Repeat, Aggregate,
|
||||
Item /* implicit from name[] */, As, Is, Single, First, Last, Tail, Skip, Take, Union, Combine, Intersect, Exclude,
|
||||
Iif, Upper, Lower, ToChars, IndexOf, Substring, StartsWith, EndsWith, Matches, MatchesFull, ReplaceMatches,
|
||||
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse,
|
||||
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, DefineVariable, Check, Today, Now, Resolve, Extension, AllFalse,
|
||||
AnyFalse, AllTrue, AnyTrue, HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString,
|
||||
ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToDate, ConvertsToTime, ToBoolean, ToInteger,
|
||||
ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo, Round, Sqrt, Abs, Ceiling, Exp, Floor, Ln, Log,
|
||||
|
@ -151,6 +151,8 @@ public class ExpressionNode {
|
|||
return Function.MemberOf;
|
||||
if (name.equals("trace"))
|
||||
return Function.Trace;
|
||||
if (name.equals("defineVariable"))
|
||||
return Function.DefineVariable;
|
||||
if (name.equals("check"))
|
||||
return Function.Check;
|
||||
if (name.equals("today"))
|
||||
|
@ -349,6 +351,8 @@ public class ExpressionNode {
|
|||
return "memberOf";
|
||||
case Trace:
|
||||
return "trace";
|
||||
case DefineVariable :
|
||||
return "defineVariable";
|
||||
case Check:
|
||||
return "check";
|
||||
case Today:
|
||||
|
|
|
@ -140,6 +140,7 @@ public class FHIRPathEngine {
|
|||
/**
|
||||
* A constant reference - e.g. a reference to a name that must be resolved in
|
||||
* context. The % will be removed from the constant name before this is invoked.
|
||||
* Variables created with defineVariable will not be processed by resolveConstant (or resolveConstantType)
|
||||
*
|
||||
* This will also be called if the host invokes the FluentPath engine with a
|
||||
* context of null
|
||||
|
@ -850,6 +851,7 @@ public class FHIRPathEngine {
|
|||
private Base thisItem;
|
||||
private List<Base> total;
|
||||
private int index;
|
||||
private Map<String, List<Base>> definedVariables;
|
||||
|
||||
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Base thisItem) {
|
||||
this.appInfo = appInfo;
|
||||
|
@ -888,6 +890,30 @@ public class FHIRPathEngine {
|
|||
index = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasDefinedVariable(String name) {
|
||||
return definedVariables != null && definedVariables.containsKey(name);
|
||||
}
|
||||
|
||||
public List<Base> getDefinedVariable(String name) {
|
||||
return definedVariables == null ? makeNull() : definedVariables.get(name);
|
||||
}
|
||||
|
||||
public void setDefinedVariable(String name, List<Base> value) {
|
||||
if (isSystemVariable(name))
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
|
||||
if (definedVariables == null) {
|
||||
definedVariables = new HashMap<String, List<Base>>();
|
||||
} else {
|
||||
if (definedVariables.containsKey(name)) {
|
||||
// Can't do this, so throw an error
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
definedVariables.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private class ExecutionTypeContext {
|
||||
|
@ -896,6 +922,7 @@ public class FHIRPathEngine {
|
|||
private TypeDetails context;
|
||||
private TypeDetails thisItem;
|
||||
private TypeDetails total;
|
||||
private Map<String, TypeDetails> definedVariables;
|
||||
|
||||
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
|
||||
super();
|
||||
|
@ -914,6 +941,29 @@ public class FHIRPathEngine {
|
|||
return thisItem;
|
||||
}
|
||||
|
||||
public boolean hasDefinedVariable(String name) {
|
||||
return definedVariables != null && definedVariables.containsKey(name);
|
||||
}
|
||||
|
||||
public TypeDetails getDefinedVariable(String name) {
|
||||
return definedVariables == null ? null : definedVariables.get(name);
|
||||
}
|
||||
|
||||
public void setDefinedVariable(String name, TypeDetails value) {
|
||||
if (isSystemVariable(name))
|
||||
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
|
||||
if (definedVariables == null) {
|
||||
definedVariables = new HashMap<String, TypeDetails>();
|
||||
} else {
|
||||
if (definedVariables.containsKey(name)) {
|
||||
// Can't do this, so throw an error
|
||||
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
||||
definedVariables.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
|
||||
|
@ -1314,6 +1364,8 @@ public class FHIRPathEngine {
|
|||
return checkParamCount(lexer, location, exp, 1);
|
||||
case Trace:
|
||||
return checkParamCount(lexer, location, exp, 1, 2);
|
||||
case DefineVariable:
|
||||
return checkParamCount(lexer, location, exp, 1, 2);
|
||||
case Check:
|
||||
return checkParamCount(lexer, location, exp, 2);
|
||||
case Today:
|
||||
|
@ -1419,9 +1471,10 @@ public class FHIRPathEngine {
|
|||
return false;
|
||||
}
|
||||
|
||||
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry)
|
||||
private List<Base> execute(ExecutionContext inContext, List<Base> focus, ExpressionNode exp, boolean atEntry)
|
||||
throws FHIRException {
|
||||
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
|
||||
ExecutionContext context = contextForParameter(inContext);
|
||||
List<Base> work = new ArrayList<Base>();
|
||||
switch (exp.getKind()) {
|
||||
case Unary:
|
||||
|
@ -1465,6 +1518,7 @@ public class FHIRPathEngine {
|
|||
ExpressionNode next = exp.getOpNext();
|
||||
ExpressionNode last = exp;
|
||||
while (next != null) {
|
||||
context = contextForParameter(inContext);
|
||||
List<Base> work2 = preOperate(work, last.getOperation(), exp);
|
||||
if (work2 != null) {
|
||||
work = work2;
|
||||
|
@ -1528,8 +1582,9 @@ public class FHIRPathEngine {
|
|||
return new TypeDetails(CollectionStatus.SINGLETON, exp.getName());
|
||||
}
|
||||
|
||||
private TypeDetails executeType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, boolean atEntry)
|
||||
private TypeDetails executeType(ExecutionTypeContext inContext, TypeDetails focus, ExpressionNode exp, boolean atEntry)
|
||||
throws PathEngineException, DefinitionException {
|
||||
ExecutionTypeContext context = contextForParameter(inContext);
|
||||
TypeDetails result = new TypeDetails(null);
|
||||
switch (exp.getKind()) {
|
||||
case Name:
|
||||
|
@ -1574,6 +1629,7 @@ public class FHIRPathEngine {
|
|||
ExpressionNode next = exp.getOpNext();
|
||||
ExpressionNode last = exp;
|
||||
while (next != null) {
|
||||
context = contextForParameter(inContext);
|
||||
TypeDetails work;
|
||||
if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
|
||||
work = executeTypeName(context, focus, next, atEntry);
|
||||
|
@ -1599,6 +1655,10 @@ public class FHIRPathEngine {
|
|||
}
|
||||
FHIRConstant c = (FHIRConstant) constant;
|
||||
if (c.getValue().startsWith("%")) {
|
||||
String varName = c.getValue().substring(1);
|
||||
if (context.hasDefinedVariable(varName)) {
|
||||
return context.getDefinedVariable(varName);
|
||||
}
|
||||
return resolveConstant(context, c.getValue(), beforeContext, expr, explicitConstant);
|
||||
} else if (c.getValue().startsWith("@")) {
|
||||
return new ArrayList<Base>(Arrays.asList(processDateConstant(context.appInfo, c.getValue().substring(1), expr)));
|
||||
|
@ -1669,6 +1729,22 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
static boolean isSystemVariable(String name){
|
||||
if (name.equals("sct"))
|
||||
return true;
|
||||
if (name.equals("loinc"))
|
||||
return true;
|
||||
if (name.equals("ucum"))
|
||||
return true;
|
||||
if (name.equals("resource"))
|
||||
return true;
|
||||
if (name.equals("rootResource"))
|
||||
return true;
|
||||
if (name.equals("context"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Base> resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr, boolean explicitConstant)
|
||||
throws PathEngineException {
|
||||
if (s.equals("%sct")) {
|
||||
|
@ -3113,8 +3189,14 @@ public class FHIRPathEngine {
|
|||
} else if (s.startsWith("%`ext-")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
|
||||
} else if (hostServices == null) {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
|
||||
} else {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
return hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
|
||||
}
|
||||
}
|
||||
|
@ -3411,6 +3493,25 @@ public class FHIRPathEngine {
|
|||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
return focus;
|
||||
}
|
||||
case DefineVariable : {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.UNORDERED, TypeDetails.FP_String));
|
||||
// set the type of the variable
|
||||
// Actually evaluate the value of the first parameter (to get the name of the variable if possible)
|
||||
// and if have that, set it into the context
|
||||
ExpressionNode p = exp.getParameters().get(0);
|
||||
if (p.getKind() == Kind.Constant && p.getConstant() != null) {
|
||||
String varName = exp.getParameters().get(0).getConstant().primitiveValue();
|
||||
if (varName != null) {
|
||||
if (paramTypes.size() > 1)
|
||||
context.setDefinedVariable(varName, paramTypes.get(1));
|
||||
else
|
||||
context.setDefinedVariable(varName, focus);
|
||||
}
|
||||
} else {
|
||||
// this variable is not a constant, so we can't analyze what name it could have
|
||||
}
|
||||
return focus;
|
||||
}
|
||||
case Check: {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
|
||||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
|
@ -3594,7 +3695,7 @@ public class FHIRPathEngine {
|
|||
|| exp.getFunction() == Function.All || exp.getFunction() == Function.Select
|
||||
|| exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
|
||||
case 1:
|
||||
return exp.getFunction() == Function.Trace;
|
||||
return exp.getFunction() == Function.Trace || exp.getFunction() == Function.DefineVariable;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -3802,6 +3903,8 @@ public class FHIRPathEngine {
|
|||
return funcMemberOf(context, focus, exp);
|
||||
case Trace:
|
||||
return funcTrace(context, focus, exp);
|
||||
case DefineVariable:
|
||||
return funcDefineVariable(context, focus, exp);
|
||||
case Check:
|
||||
return funcCheck(context, focus, exp);
|
||||
case Today:
|
||||
|
@ -4536,11 +4639,48 @@ public class FHIRPathEngine {
|
|||
private ExecutionContext changeThis(ExecutionContext context, Base newThis) {
|
||||
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
|
||||
newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionContext contextForParameter(ExecutionContext context) {
|
||||
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.thisItem);
|
||||
newContext.total = context.total;
|
||||
newContext.index = context.index;
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
|
||||
return new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
|
||||
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
|
||||
// append all of the defined variables from the context into the new context
|
||||
if (context.definedVariables != null) {
|
||||
for (String s : context.definedVariables.keySet()) {
|
||||
newContext.setDefinedVariable(s, context.definedVariables.get(s));
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
private List<Base> funcNow(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
|
||||
|
@ -5368,6 +5508,20 @@ public class FHIRPathEngine {
|
|||
return focus;
|
||||
}
|
||||
|
||||
private List<Base> funcDefineVariable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||
String name = nl.get(0).primitiveValue();
|
||||
List<Base> value;
|
||||
if (exp.getParameters().size() == 2) {
|
||||
value = execute(context, focus, exp.getParameters().get(1), true);
|
||||
} else {
|
||||
value = focus;
|
||||
}
|
||||
// stash the variable into the context
|
||||
context.setDefinedVariable(name, value);
|
||||
return focus;
|
||||
}
|
||||
|
||||
private List<Base> funcCheck(ExecutionContext context, List<Base> focus, ExpressionNode expr) throws FHIRException {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (!convertToBoolean(n1)) {
|
||||
|
|
|
@ -3202,12 +3202,14 @@ public class FHIRPathEngine {
|
|||
} else if (s.startsWith("%`ext-")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
|
||||
} else if (hostServices == null) {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
|
||||
} else {
|
||||
String varName = s.substring(1);
|
||||
if (context.hasDefinedVariable(varName)) {
|
||||
if (context.hasDefinedVariable(varName))
|
||||
return context.getDefinedVariable(varName);
|
||||
}
|
||||
TypeDetails v = hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
|
||||
if (v == null) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
|
||||
|
|
Loading…
Reference in New Issue