diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/ExpressionNode.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/ExpressionNode.java
index a061937a9..3ed27a087 100644
--- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/ExpressionNode.java
+++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/ExpressionNode.java
@@ -34,6 +34,7 @@ package org.hl7.fhir.r4.model;
import java.util.ArrayList;
import java.util.List;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.Utilities;
public class ExpressionNode {
@@ -41,31 +42,6 @@ public class ExpressionNode {
public enum Kind {
Name, Function, Constant, Group, Unary
}
- public static class SourceLocation {
- private int line;
- private int column;
- public SourceLocation(int line, int column) {
- super();
- this.line = line;
- this.column = column;
- }
- public int getLine() {
- return line;
- }
- public int getColumn() {
- return column;
- }
- public void setLine(int line) {
- this.line = line;
- }
- public void setColumn(int column) {
- this.column = column;
- }
-
- public String toString() {
- return Integer.toString(line)+", "+Integer.toString(column);
- }
- }
public enum Function {
Custom,
diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRLexer.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRLexer.java
index 38df5e9a4..83619c66b 100644
--- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRLexer.java
+++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRLexer.java
@@ -34,7 +34,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.model.ExpressionNode;
-import org.hl7.fhir.r4.model.ExpressionNode.SourceLocation;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.Utilities;
// shared lexer for concrete syntaxes
diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRPathEngine.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRPathEngine.java
index 89f805006..7bc7ec1c0 100644
--- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRPathEngine.java
+++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/FHIRPathEngine.java
@@ -19,6 +19,7 @@ import org.hl7.fhir.r4.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r4.model.TypeDetails.ProfiledType;
import org.hl7.fhir.r4.utils.FHIRLexer.FHIRLexerException;
import org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.TerminologyServiceOptions;
import org.hl7.fhir.utilities.Utilities;
@@ -414,10 +415,10 @@ public class FHIRPathEngine {
}
StructureDefinition sd = worker.fetchResource(StructureDefinition.class, ctxt);
if (sd == null)
- throw new PathEngineException("Unknown context "+context);
- ElementDefinitionMatch ed = getElementDefinition(sd, context, true);
+ throw new PathEngineException("Unknown context "+context, expr.getStart(), expr.toString());
+ ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null)
- throw new PathEngineException("Unknown context element "+context);
+ throw new PathEngineException("Unknown context element "+context, expr.getStart(), expr.toString());
if (ed.fixedType != null)
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType()))
@@ -438,9 +439,9 @@ public class FHIRPathEngine {
if (!context.contains(".")) {
types = new TypeDetails(CollectionStatus.SINGLETON, sd.getUrl());
} else {
- ElementDefinitionMatch ed = getElementDefinition(sd, context, true);
+ ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null)
- throw new PathEngineException("Unknown context element "+context);
+ throw new PathEngineException("Unknown context element "+context, expr.getStart(), expr.toString());
if (ed.fixedType != null)
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType()))
@@ -1161,7 +1162,7 @@ public class FHIRPathEngine {
work.addAll(work2);
break;
case Constant:
- Base b = resolveConstant(context, exp.getConstant(), false);
+ Base b = resolveConstant(context, exp.getConstant(), false, exp);
if (b != null)
work.add(b);
break;
@@ -1177,15 +1178,15 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
- List work2 = preOperate(work, last.getOperation());
+ List work2 = preOperate(work, last.getOperation(), exp);
if (work2 != null)
work = work2;
else if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
work2 = executeTypeName(context, focus, next, false);
- work = operate(context, work, last.getOperation(), work2);
+ work = operate(context, work, last.getOperation(), work2, last);
} else {
work2 = execute(context, focus, next, true);
- work = operate(context, work, last.getOperation(), work2);
+ work = operate(context, work, last.getOperation(), work2, last);
// System.out.println("Result of {'"+last.toString()+" "+last.getOperation().toCode()+" "+next.toString()+"'}: "+focus.toString());
}
last = next;
@@ -1206,7 +1207,7 @@ public class FHIRPathEngine {
}
- private List preOperate(List left, Operation operation) throws PathEngineException {
+ private List preOperate(List left, Operation operation, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0)
return null;
switch (operation) {
@@ -1215,7 +1216,7 @@ public class FHIRPathEngine {
case Or:
return isBoolean(left, true) ? makeBoolean(true) : null;
case Implies:
- Equality v = asBool(left);
+ Equality v = asBool(left, expr);
return v == Equality.False ? makeBoolean(true) : null;
default:
return null;
@@ -1246,13 +1247,13 @@ public class FHIRPathEngine {
else if (atEntry && exp.getName().equals("$total"))
result.update(anything(CollectionStatus.UNORDERED));
else if (atEntry && focus == null)
- result.update(executeContextType(context, exp.getName()));
+ result.update(executeContextType(context, exp.getName(), exp));
else {
for (String s : focus.getTypes()) {
result.update(executeType(s, exp, atEntry));
}
if (result.hasNoTypes())
- throw new PathEngineException("The name "+exp.getName()+" is not valid for any of the possible types: "+focus.describe());
+ throw new PathEngineException("The name "+exp.getName()+" is not valid for any of the possible types: "+focus.describe(), exp.getStart(), exp.toString());
}
break;
case Function:
@@ -1262,7 +1263,7 @@ public class FHIRPathEngine {
result.addType("integer");
break;
case Constant:
- result.update(resolveConstantType(context, exp.getConstant()));
+ result.update(resolveConstantType(context, exp.getConstant(), exp));
break;
case Group:
result.update(executeType(context, focus, exp.getGroup(), atEntry));
@@ -1282,7 +1283,7 @@ public class FHIRPathEngine {
work = executeTypeName(context, focus, next, atEntry);
else
work = executeType(context, focus, next, atEntry);
- result = operateTypes(result, last.getOperation(), work);
+ result = operateTypes(result, last.getOperation(), work, exp);
last = next;
next = next.getOpNext();
}
@@ -1291,16 +1292,16 @@ public class FHIRPathEngine {
return result;
}
- private Base resolveConstant(ExecutionContext context, Base constant, boolean beforeContext) throws PathEngineException {
+ private Base resolveConstant(ExecutionContext context, Base constant, boolean beforeContext, ExpressionNode expr) throws PathEngineException {
if (!(constant instanceof FHIRConstant))
return constant;
FHIRConstant c = (FHIRConstant) constant;
if (c.getValue().startsWith("%")) {
- return resolveConstant(context, c.getValue(), beforeContext);
+ return resolveConstant(context, c.getValue(), beforeContext, expr);
} else if (c.getValue().startsWith("@")) {
return processDateConstant(context.appInfo, c.getValue().substring(1));
} else
- throw new PathEngineException("Invaild FHIR Constant "+c.getValue());
+ throw new PathEngineException("Invaild FHIR Constant "+c.getValue(), expr.getStart(), expr.toString());
}
private Base processDateConstant(Object appInfo, String value) throws PathEngineException {
@@ -1322,7 +1323,7 @@ public class FHIRPathEngine {
}
- private Base resolveConstant(ExecutionContext context, String s, boolean beforeContext) throws PathEngineException {
+ private Base resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr) throws PathEngineException {
if (s.equals("%sct"))
return new StringType("http://snomed.info/sct").noExtensions();
else if (s.equals("%loinc"))
@@ -1331,11 +1332,11 @@ public class FHIRPathEngine {
return new StringType("http://unitsofmeasure.org").noExtensions();
else if (s.equals("%resource")) {
if (context.focusResource == null)
- throw new PathEngineException("Cannot use %resource in this context");
+ throw new PathEngineException("Cannot use %resource in this context", expr.getStart(), expr.toString());
return context.focusResource;
} else if (s.equals("%rootResource")) {
if (context.rootResource == null)
- throw new PathEngineException("Cannot use %rootResource in this context");
+ throw new PathEngineException("Cannot use %rootResource in this context", expr.getStart(), expr.toString());
return context.rootResource;
} else if (s.equals("%context")) {
return context.context;
@@ -1348,7 +1349,7 @@ public class FHIRPathEngine {
else if (s.startsWith("%`ext-"))
return new StringType("http://hl7.org/fhir/StructureDefinition/"+s.substring(6, s.length()-1)).noExtensions();
else if (hostServices == null)
- throw new PathEngineException("Unknown fixed constant '"+s+"'");
+ throw new PathEngineException("Unknown fixed constant '"+s+"'", expr.getStart(), expr.toString());
else
return hostServices.resolveConstant(context.appInfo, s.substring(1), beforeContext);
}
@@ -1408,39 +1409,39 @@ public class FHIRPathEngine {
}
- private List operate(ExecutionContext context, List left, Operation operation, List right) throws FHIRException {
+ private List operate(ExecutionContext context, List left, Operation operation, List right, ExpressionNode expr) throws FHIRException {
switch (operation) {
case Equals: return opEquals(left, right);
- case Equivalent: return opEquivalent(left, right);
- case NotEquals: return opNotEquals(left, right);
- case NotEquivalent: return opNotEquivalent(left, right);
- case LessThan: return opLessThan(left, right);
- case Greater: return opGreater(left, right);
- case LessOrEqual: return opLessOrEqual(left, right);
- case GreaterOrEqual: return opGreaterOrEqual(left, right);
- case Union: return opUnion(left, right);
- case In: return opIn(left, right);
- case MemberOf: return opMemberOf(context, left, right);
- case Contains: return opContains(left, right);
- case Or: return opOr(left, right);
- case And: return opAnd(left, right);
- case Xor: return opXor(left, right);
- case Implies: return opImplies(left, right);
- case Plus: return opPlus(left, right);
- case Times: return opTimes(left, right);
- case Minus: return opMinus(left, right);
- case Concatenate: return opConcatenate(left, right);
- case DivideBy: return opDivideBy(left, right);
- case Div: return opDiv(left, right);
- case Mod: return opMod(left, right);
- case Is: return opIs(left, right);
- case As: return opAs(left, right);
+ case Equivalent: return opEquivalent(left, right, expr);
+ case NotEquals: return opNotEquals(left, right, expr);
+ case NotEquivalent: return opNotEquivalent(left, right, expr);
+ case LessThan: return opLessThan(left, right, expr);
+ case Greater: return opGreater(left, right, expr);
+ case LessOrEqual: return opLessOrEqual(left, right, expr);
+ case GreaterOrEqual: return opGreaterOrEqual(left, right, expr);
+ case Union: return opUnion(left, right, expr);
+ case In: return opIn(left, right, expr);
+ case MemberOf: return opMemberOf(context, left, right, expr);
+ case Contains: return opContains(left, right, expr);
+ case Or: return opOr(left, right, expr);
+ case And: return opAnd(left, right, expr);
+ case Xor: return opXor(left, right, expr);
+ case Implies: return opImplies(left, right, expr);
+ case Plus: return opPlus(left, right, expr);
+ case Times: return opTimes(left, right, expr);
+ case Minus: return opMinus(left, right, expr);
+ case Concatenate: return opConcatenate(left, right, expr);
+ case DivideBy: return opDivideBy(left, right, expr);
+ case Div: return opDiv(left, right, expr);
+ case Mod: return opMod(left, right, expr);
+ case Is: return opIs(left, right, expr);
+ case As: return opAs(left, right, expr);
default:
throw new Error("Not Done Yet: "+operation.toCode());
}
}
- private List opAs(List left, List right) {
+ private List opAs(List left, List right, ExpressionNode expr) {
List result = new ArrayList<>();
if (right.size() != 1)
return result;
@@ -1455,7 +1456,7 @@ public class FHIRPathEngine {
}
- private List opIs(List left, List right) {
+ private List opIs(List left, List right, ExpressionNode expr) {
List result = new ArrayList();
if (left.size() != 1 || right.size() != 1)
result.add(new BooleanType(false).noExtensions());
@@ -1472,7 +1473,7 @@ public class FHIRPathEngine {
}
- private TypeDetails operateTypes(TypeDetails left, Operation operation, TypeDetails right) {
+ private TypeDetails operateTypes(TypeDetails left, Operation operation, TypeDetails right, ExpressionNode expr) {
switch (operation) {
case Equals: return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Equivalent: return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
@@ -1518,7 +1519,7 @@ public class FHIRPathEngine {
if (right.hasType(worker, "Quantity")) {
result.addType(left.getType());
} else {
- throw new PathEngineException(String.format("Error in date arithmetic: Unable to add type {0} to {1}", right.getType(), left.getType()));
+ throw new PathEngineException(String.format("Error in date arithmetic: Unable to add type {0} to {1}", right.getType(), left.getType()), expr.getStart(), expr.toString());
}
}
return result;
@@ -1579,7 +1580,7 @@ public class FHIRPathEngine {
return makeBoolean(res);
}
- private List opNotEquals(List left, List right) {
+ private List opNotEquals(List left, List right, ExpressionNode expr) {
if (!legacyMode && (left.size() == 0 || right.size() == 0))
return new ArrayList();
@@ -1648,9 +1649,9 @@ public class FHIRPathEngine {
}
- private boolean doEquivalent(Base left, Base right) throws PathEngineException {
+ private boolean doEquivalent(Base left, Base right, ExpressionNode expr) throws PathEngineException {
if (left instanceof Quantity && right instanceof Quantity)
- return qtyEquivalent((Quantity) left, (Quantity) right);
+ return qtyEquivalent((Quantity) left, (Quantity) right, expr);
if (left.hasType("integer") && right.hasType("integer"))
return doEquals(left, right);
if (left.hasType("boolean") && right.hasType("boolean"))
@@ -1662,7 +1663,7 @@ public class FHIRPathEngine {
if (left.hasType(FHIR_TYPES_STRING) && right.hasType(FHIR_TYPES_STRING))
return Utilities.equivalent(convertToString(left), convertToString(right));
- throw new PathEngineException(String.format("Unable to determine equivalence between %s and %s", left.fhirType(), right.fhirType()));
+ throw new PathEngineException(String.format("Unable to determine equivalence between %s and %s", left.fhirType(), right.fhirType()), expr.getStart(), expr.toString());
}
private boolean qtyEqual(Quantity left, Quantity right) {
@@ -1703,19 +1704,19 @@ public class FHIRPathEngine {
}
- private boolean qtyEquivalent(Quantity left, Quantity right) throws PathEngineException {
+ private boolean qtyEquivalent(Quantity left, Quantity right, ExpressionNode expr) throws PathEngineException {
if (worker.getUcumService() != null) {
DecimalType dl = qtyToCanonical(left);
DecimalType dr = qtyToCanonical(right);
if (dl != null && dr != null)
- return doEquivalent(dl, dr);
+ return doEquivalent(dl, dr, expr);
}
return left.equals(right);
}
- private List opEquivalent(List left, List right) throws PathEngineException {
+ private List opEquivalent(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() != right.size())
return makeBoolean(false);
@@ -1723,7 +1724,7 @@ public class FHIRPathEngine {
for (int i = 0; i < left.size(); i++) {
boolean found = false;
for (int j = 0; j < right.size(); j++) {
- if (doEquivalent(left.get(i), right.get(j))) {
+ if (doEquivalent(left.get(i), right.get(j), expr)) {
found = true;
break;
}
@@ -1736,7 +1737,7 @@ public class FHIRPathEngine {
return makeBoolean(res);
}
- private List opNotEquivalent(List left, List right) throws PathEngineException {
+ private List opNotEquivalent(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() != right.size())
return makeBoolean(true);
@@ -1744,7 +1745,7 @@ public class FHIRPathEngine {
for (int i = 0; i < left.size(); i++) {
boolean found = false;
for (int j = 0; j < right.size(); j++) {
- if (doEquivalent(left.get(i), right.get(j))) {
+ if (doEquivalent(left.get(i), right.get(j), expr)) {
found = true;
break;
}
@@ -1759,7 +1760,7 @@ public class FHIRPathEngine {
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary", "canonical", "url"};
- private List opLessThan(List left, List right) throws FHIRException {
+ private List opLessThan(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
@@ -1775,12 +1776,12 @@ public class FHIRPathEngine {
else if ((l.hasType("time")) && (r.hasType("time")))
return makeBoolean(l.primitiveValue().compareTo(r.primitiveValue()) < 0);
else
- throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType());
+ throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType(), expr.getStart(), expr.toString());
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("code");
List rUnit = right.get(0).listChildrenByName("code");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opLessThan(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opLessThan(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null)
return makeBoolean(false);
@@ -1789,14 +1790,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonical((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonical((Quantity) right.get(0)));
- return opLessThan(dl, dr);
+ return opLessThan(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opGreater(List left, List right) throws FHIRException {
+ private List opGreater(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
@@ -1811,12 +1812,12 @@ public class FHIRPathEngine {
else if ((l.hasType("time")) && (r.hasType("time")))
return makeBoolean(l.primitiveValue().compareTo(r.primitiveValue()) > 0);
else
- throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType());
+ throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType(), expr.getStart(), expr.toString());
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("unit");
List rUnit = right.get(0).listChildrenByName("unit");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opGreater(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opGreater(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null)
return makeBoolean(false);
@@ -1825,14 +1826,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonical((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonical((Quantity) right.get(0)));
- return opGreater(dl, dr);
+ return opGreater(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opLessOrEqual(List left, List right) throws FHIRException {
+ private List opLessOrEqual(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
@@ -1847,14 +1848,14 @@ public class FHIRPathEngine {
else if ((l.hasType("time")) && (r.hasType("time")))
return makeBoolean(l.primitiveValue().compareTo(r.primitiveValue()) <= 0);
else
- throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType());
+ throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType(), expr.getStart(), expr.toString());
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnits = left.get(0).listChildrenByName("unit");
String lunit = lUnits.size() == 1 ? lUnits.get(0).primitiveValue() : null;
List rUnits = right.get(0).listChildrenByName("unit");
String runit = rUnits.size() == 1 ? rUnits.get(0).primitiveValue() : null;
if ((lunit == null && runit == null) || lunit.equals(runit)) {
- return opLessOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opLessOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null)
return makeBoolean(false);
@@ -1863,14 +1864,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonical((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonical((Quantity) right.get(0)));
- return opLessOrEqual(dl, dr);
+ return opLessOrEqual(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opGreaterOrEqual(List left, List right) throws FHIRException {
+ private List opGreaterOrEqual(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
@@ -1885,12 +1886,12 @@ public class FHIRPathEngine {
else if ((l.hasType("time")) && (r.hasType("time")))
return makeBoolean(l.primitiveValue().compareTo(r.primitiveValue()) >= 0);
else
- throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType());
+ throw new PathEngineException("Unable to compare values of type "+l.fhirType()+" and "+r.fhirType(), expr.getStart(), expr.toString());
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("unit");
List rUnit = right.get(0).listChildrenByName("unit");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opGreaterOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opGreaterOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null)
return makeBoolean(false);
@@ -1899,14 +1900,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonical((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonical((Quantity) right.get(0)));
- return opGreaterOrEqual(dl, dr);
+ return opGreaterOrEqual(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opMemberOf(ExecutionContext context, List left, List right) throws FHIRException {
+ private List opMemberOf(ExecutionContext context, List left, List right, ExpressionNode expr) throws FHIRException {
boolean ans = false;
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, right.get(0).primitiveValue()) : worker.fetchResource(ValueSet.class, right.get(0).primitiveValue());
if (vs != null) {
@@ -1926,7 +1927,7 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opIn(List left, List right) throws FHIRException {
+ private List opIn(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0)
return new ArrayList();
if (right.size() == 0)
@@ -1949,7 +1950,7 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opContains(List left, List right) {
+ private List opContains(List left, List right, ExpressionNode expr) {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
boolean ans = true;
@@ -1970,17 +1971,17 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opPlus(List left, List right) throws PathEngineException {
+ private List opPlus(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing +: left operand has more than one value");
+ throw new PathEngineException("Error performing +: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive())
- throw new PathEngineException(String.format("Error performing +: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing +: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing +: right operand has more than one value");
+ throw new PathEngineException("Error performing +: right operand has more than one value", expr.getStart(), expr.toString());
if (!right.get(0).isPrimitive() && !((left.get(0).isDateTime() || "0".equals(left.get(0).primitiveValue()) || left.get(0).hasType("Quantity")) && right.get(0).hasType("Quantity")))
- throw new PathEngineException(String.format("Error performing +: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing +: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -1992,13 +1993,13 @@ public class FHIRPathEngine {
else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer"))
result.add(new DecimalType(new BigDecimal(l.primitiveValue()).add(new BigDecimal(r.primitiveValue()))));
else if (l.isDateTime() && r.hasType("Quantity"))
- result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, false));
+ result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, false, expr));
else
- throw new PathEngineException(String.format("Error performing +: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing +: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private BaseDateTimeType dateAdd(BaseDateTimeType d, Quantity q, boolean negate) {
+ private BaseDateTimeType dateAdd(BaseDateTimeType d, Quantity q, boolean negate, ExpressionNode expr) {
BaseDateTimeType result = (BaseDateTimeType) d.copy();
int value = negate ? 0 - q.getValue().intValue() : q.getValue().intValue();
@@ -2008,13 +2009,13 @@ public class FHIRPathEngine {
result.add(Calendar.YEAR, value);
break;
case "a":
- throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()));
+ throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()), expr.getStart(), expr.toString());
case "months":
case "month":
result.add(Calendar.MONTH, value);
break;
case "mo":
- throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()));
+ throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()), expr.getStart(), expr.toString());
case "weeks":
case "week":
case "wk":
@@ -2046,23 +2047,23 @@ public class FHIRPathEngine {
result.add(Calendar.MILLISECOND, value);
break;
default:
- throw new PathEngineException(String.format("Error in date arithmetic: unrecognized time unit %s", q.getCode()));
+ throw new PathEngineException(String.format("Error in date arithmetic: unrecognized time unit %s", q.getCode()), expr.getStart(), expr.toString());
}
return result;
}
- private List opTimes(List left, List right) throws PathEngineException {
+ private List opTimes(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing *: left operand has more than one value");
+ throw new PathEngineException("Error performing *: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing +: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing +: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing *: right operand has more than one value");
+ throw new PathEngineException("Error performing *: right operand has more than one value", expr.getStart(), expr.toString());
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing *: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing *: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -2080,23 +2081,23 @@ public class FHIRPathEngine {
p = worker.getUcumService().multiply(pl, pr);
result.add(pairToQty(p));
} catch (UcumException e) {
- throw new PathEngineException(e.getMessage(), e);
+ throw new PathEngineException(e.getMessage(), expr.getOpStart(), expr.toString(), e);
}
} else
- throw new PathEngineException(String.format("Error performing *: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing *: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private List opConcatenate(List left, List right) throws PathEngineException {
+ private List opConcatenate(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() > 1)
- throw new PathEngineException("Error performing &: left operand has more than one value");
+ throw new PathEngineException("Error performing &: left operand has more than one value", expr.getStart(), expr.toString());
if (left.size() > 0 && !left.get(0).hasType(FHIR_TYPES_STRING))
- throw new PathEngineException(String.format("Error performing &: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing &: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing &: right operand has more than one value");
+ throw new PathEngineException("Error performing &: right operand has more than one value", expr.getStart(), expr.toString());
if (right.size() > 0 && !right.get(0).hasType(FHIR_TYPES_STRING))
- throw new PathEngineException(String.format("Error performing &: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing &: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
String l = left.size() == 0 ? "" : left.get(0).primitiveValue();
@@ -2105,7 +2106,7 @@ public class FHIRPathEngine {
return result;
}
- private List opUnion(List left, List right) {
+ private List opUnion(List left, List right, ExpressionNode expr) {
List result = new ArrayList();
for (Base item : left) {
if (!doContains(result, item))
@@ -2128,9 +2129,9 @@ public class FHIRPathEngine {
}
- private List opAnd(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opAnd(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case False: return makeBoolean(false);
case Null:
@@ -2152,9 +2153,9 @@ public class FHIRPathEngine {
return list.size() == 1 && list.get(0) instanceof BooleanType && ((BooleanType) list.get(0)).booleanValue() == b;
}
- private List opOr(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opOr(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case True: return makeBoolean(true);
case Null:
@@ -2172,9 +2173,9 @@ public class FHIRPathEngine {
return makeNull();
}
- private List opXor(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opXor(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case True:
switch (r) {
@@ -2194,13 +2195,13 @@ public class FHIRPathEngine {
return makeNull();
}
- private List opImplies(List left, List right) throws PathEngineException {
- Equality eq = asBool(left);
+ private List opImplies(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality eq = asBool(left, expr);
if (eq == Equality.False)
return makeBoolean(true);
else if (right.size() == 0)
return makeNull();
- else switch (asBool(right)) {
+ else switch (asBool(right, expr)) {
case False: return eq == Equality.Null ? makeNull() : makeBoolean(false);
case Null: return makeNull();
case True: return makeBoolean(true);
@@ -2209,17 +2210,17 @@ public class FHIRPathEngine {
}
- private List opMinus(List left, List right) throws PathEngineException {
+ private List opMinus(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing -: left operand has more than one value");
+ throw new PathEngineException("Error performing -: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive())
- throw new PathEngineException(String.format("Error performing -: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing -: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing -: right operand has more than one value");
+ throw new PathEngineException("Error performing -: right operand has more than one value", expr.getStart(), expr.toString());
if (!right.get(0).isPrimitive() && !((left.get(0).isDateTime() || "0".equals(left.get(0).primitiveValue()) || left.get(0).hasType("Quantity")) && right.get(0).hasType("Quantity")))
- throw new PathEngineException(String.format("Error performing -: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing -: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -2230,23 +2231,23 @@ public class FHIRPathEngine {
else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer"))
result.add(new DecimalType(new BigDecimal(l.primitiveValue()).subtract(new BigDecimal(r.primitiveValue()))));
else if (l.isDateTime() && r.hasType("Quantity"))
- result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, true));
+ result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, true, expr));
else
- throw new PathEngineException(String.format("Error performing -: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing -: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private List opDivideBy(List left, List right) throws PathEngineException {
+ private List opDivideBy(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing /: left operand has more than one value");
+ throw new PathEngineException("Error performing /: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing -: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing -: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
throw new PathEngineException("Error performing /: right operand has more than one value");
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing /: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing /: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -2269,24 +2270,24 @@ public class FHIRPathEngine {
p = worker.getUcumService().multiply(pl, pr);
result.add(pairToQty(p));
} catch (UcumException e) {
- throw new PathEngineException(e.getMessage(), e);
+ throw new PathEngineException(e.getMessage(), expr.getOpStart(), expr.toString(), e);
}
} else
- throw new PathEngineException(String.format("Error performing /: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing /: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private List opDiv(List left, List right) throws PathEngineException {
+ private List opDiv(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing div: left operand has more than one value");
+ throw new PathEngineException("Error performing div: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing div: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing div: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing div: right operand has more than one value");
+ throw new PathEngineException("Error performing div: right operand has more than one value", expr.getStart(), expr.toString());
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity))
- throw new PathEngineException(String.format("Error performing div: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing div: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -2305,21 +2306,21 @@ public class FHIRPathEngine {
}
}
else
- throw new PathEngineException(String.format("Error performing div: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing div: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private List opMod(List left, List right) throws PathEngineException {
+ private List opMod(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() > 1)
- throw new PathEngineException("Error performing mod: left operand has more than one value");
+ throw new PathEngineException("Error performing mod: left operand has more than one value", expr.getStart(), expr.toString());
if (!left.get(0).isPrimitive())
- throw new PathEngineException(String.format("Error performing mod: left operand has the wrong type (%s)", left.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing mod: left operand has the wrong type (%s)", left.get(0).fhirType()), expr.getStart(), expr.toString());
if (right.size() > 1)
- throw new PathEngineException("Error performing mod: right operand has more than one value");
+ throw new PathEngineException("Error performing mod: right operand has more than one value", expr.getStart(), expr.toString());
if (!right.get(0).isPrimitive())
- throw new PathEngineException(String.format("Error performing mod: right operand has the wrong type (%s)", right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing mod: right operand has the wrong type (%s)", right.get(0).fhirType()), expr.getStart(), expr.toString());
List result = new ArrayList();
Base l = left.get(0);
@@ -2338,12 +2339,12 @@ public class FHIRPathEngine {
}
}
else
- throw new PathEngineException(String.format("Error performing mod: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
+ throw new PathEngineException(String.format("Error performing mod: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()), expr.getStart(), expr.toString());
return result;
}
- private TypeDetails resolveConstantType(ExecutionTypeContext context, Base constant) throws PathEngineException {
+ private TypeDetails resolveConstantType(ExecutionTypeContext context, Base constant, ExpressionNode expr) throws PathEngineException {
if (constant instanceof BooleanType)
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
else if (constant instanceof IntegerType)
@@ -2353,12 +2354,12 @@ public class FHIRPathEngine {
else if (constant instanceof Quantity)
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Quantity);
else if (constant instanceof FHIRConstant)
- return resolveConstantType(context, ((FHIRConstant) constant).getValue());
+ return resolveConstantType(context, ((FHIRConstant) constant).getValue(), expr);
else
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
- private TypeDetails resolveConstantType(ExecutionTypeContext context, String s) throws PathEngineException {
+ private TypeDetails resolveConstantType(ExecutionTypeContext context, String s, ExpressionNode expr) throws PathEngineException {
if (s.startsWith("@")) {
if (s.startsWith("@T"))
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time);
@@ -2372,11 +2373,11 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
else if (s.equals("%resource")) {
if (context.resource == null)
- throw new PathEngineException("%resource cannot be used in this context");
+ throw new PathEngineException("%resource cannot be used in this context", expr.getStart(), expr.toString());
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
} else if (s.equals("%rootResource")) {
if (context.resource == null)
- throw new PathEngineException("%rootResource cannot be used in this context");
+ throw new PathEngineException("%rootResource cannot be used in this context", expr.getStart(), expr.toString());
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
} else if (s.equals("%context")) {
return context.context;
@@ -2391,7 +2392,7 @@ public class FHIRPathEngine {
else if (s.startsWith("%`ext-"))
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
else if (hostServices == null)
- throw new PathEngineException("Unknown fixed constant type for '"+s+"'");
+ throw new PathEngineException("Unknown fixed constant type for '"+s+"'", expr.getStart(), expr.toString());
else
return hostServices.resolveConstantType(context.appInfo, s);
}
@@ -2422,9 +2423,9 @@ public class FHIRPathEngine {
return result;
}
- private TypeDetails executeContextType(ExecutionTypeContext context, String name) throws PathEngineException, DefinitionException {
+ private TypeDetails executeContextType(ExecutionTypeContext context, String name, ExpressionNode expr) throws PathEngineException, DefinitionException {
if (hostServices == null)
- throw new PathEngineException("Unable to resolve context reference since no host services are provided");
+ throw new PathEngineException("Unable to resolve context reference since no host services are provided", expr.getStart(), expr.toString());
return hostServices.resolveConstantType(context.appInfo, name);
}
@@ -2432,7 +2433,7 @@ public class FHIRPathEngine {
if (atEntry && Character.isUpperCase(exp.getName().charAt(0)) && hashTail(type).equals(exp.getName())) // special case for start up
return new TypeDetails(CollectionStatus.SINGLETON, type);
TypeDetails result = new TypeDetails(null);
- getChildTypesByName(type, exp.getName(), result);
+ getChildTypesByName(type, exp.getName(), result, exp);
return result;
}
@@ -2462,11 +2463,11 @@ public class FHIRPathEngine {
case Exists :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case SubsetOf : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, focus);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, focus);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case SupersetOf : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, focus);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, focus);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case IsDistinct :
@@ -2486,16 +2487,16 @@ public class FHIRPathEngine {
case Aggregate :
return anything(focus.getCollectionStatus());
case Item : {
- checkOrdered(focus, "item");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "item", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case As : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName());
}
case OfType : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName());
}
case Type : {
@@ -2513,31 +2514,31 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_ClassInfo);
}
case Is : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Single :
return focus.toSingleton();
case First : {
- checkOrdered(focus, "first");
+ checkOrdered(focus, "first", exp);
return focus.toSingleton();
}
case Last : {
- checkOrdered(focus, "last");
+ checkOrdered(focus, "last", exp);
return focus.toSingleton();
}
case Tail : {
- checkOrdered(focus, "tail");
+ checkOrdered(focus, "tail", exp);
return focus;
}
case Skip : {
- checkOrdered(focus, "skip");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "skip", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case Take : {
- checkOrdered(focus, "take");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "take", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case Union : {
@@ -2560,76 +2561,76 @@ public class FHIRPathEngine {
return types;
}
case Lower : {
- checkContextString(focus, "lower");
+ checkContextString(focus, "lower", exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Upper : {
- checkContextString(focus, "upper");
+ checkContextString(focus, "upper", exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case ToChars : {
- checkContextString(focus, "toChars");
+ checkContextString(focus, "toChars", exp);
return new TypeDetails(CollectionStatus.ORDERED, TypeDetails.FP_String);
}
case IndexOf : {
- checkContextString(focus, "indexOf");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "indexOf", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case Substring : {
- checkContextString(focus, "subString");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkContextString(focus, "subString", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case StartsWith : {
- checkContextString(focus, "startsWith");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "startsWith", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case EndsWith : {
- checkContextString(focus, "endsWith");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "endsWith", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Matches : {
- checkContextString(focus, "matches");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "matches", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ReplaceMatches : {
- checkContextString(focus, "replaceMatches");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "replaceMatches", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Contains : {
- checkContextString(focus, "contains");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "contains", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Replace : {
- checkContextString(focus, "replace");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, "string"), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "replace", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, "string"), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Length : {
- checkContextPrimitive(focus, "length", false);
+ checkContextPrimitive(focus, "length", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case Children :
- return childTypes(focus, "*");
+ return childTypes(focus, "*", exp);
case Descendants :
- return childTypes(focus, "**");
+ return childTypes(focus, "**", exp);
case MemberOf : {
- checkContextCoded(focus, "memberOf");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextCoded(focus, "memberOf", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Trace : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case Check : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case Today :
@@ -2637,11 +2638,11 @@ public class FHIRPathEngine {
case Now :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
case Resolve : {
- checkContextReference(focus, "resolve");
+ checkContextReference(focus, "resolve", exp);
return new TypeDetails(CollectionStatus.SINGLETON, "DomainResource");
}
case Extension : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, "Extension");
}
case AnyTrue:
@@ -2657,42 +2658,42 @@ public class FHIRPathEngine {
case HtmlChecks :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias :
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
case AliasAs :
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
case ToInteger : {
- checkContextPrimitive(focus, "toInteger", true);
+ checkContextPrimitive(focus, "toInteger", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case ToDecimal : {
- checkContextPrimitive(focus, "toDecimal", true);
+ checkContextPrimitive(focus, "toDecimal", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
}
case ToString : {
- checkContextPrimitive(focus, "toString", true);
+ checkContextPrimitive(focus, "toString", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case ToQuantity : {
- checkContextPrimitive(focus, "toQuantity", true);
+ checkContextPrimitive(focus, "toQuantity", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Quantity);
}
case ToBoolean : {
- checkContextPrimitive(focus, "toBoolean", false);
+ checkContextPrimitive(focus, "toBoolean", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ToDateTime : {
- checkContextPrimitive(focus, "toBoolean", false);
+ checkContextPrimitive(focus, "toBoolean", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
}
case ToTime : {
- checkContextPrimitive(focus, "toBoolean", false);
+ checkContextPrimitive(focus, "toBoolean", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time);
}
case ConvertsToString :
case ConvertsToQuantity :{
- checkContextPrimitive(focus, exp.getFunction().toCode(), true);
+ checkContextPrimitive(focus, exp.getFunction().toCode(), true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ConvertsToInteger :
@@ -2700,11 +2701,11 @@ public class FHIRPathEngine {
case ConvertsToDateTime :
case ConvertsToTime :
case ConvertsToBoolean : {
- checkContextPrimitive(focus, exp.getFunction().toCode(), false);
+ checkContextPrimitive(focus, exp.getFunction().toCode(), false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ConformsTo: {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Custom : {
@@ -2717,7 +2718,7 @@ public class FHIRPathEngine {
}
- private void checkParamTypes(String funcName, List paramTypes, TypeDetails... typeSet) throws PathEngineException {
+ private void checkParamTypes(ExpressionNode expr, String funcName, List paramTypes, TypeDetails... typeSet) throws PathEngineException {
int i = 0;
for (TypeDetails pt : typeSet) {
if (i == paramTypes.size())
@@ -2726,47 +2727,47 @@ public class FHIRPathEngine {
i++;
for (String a : actual.getTypes()) {
if (!pt.hasType(worker, a))
- throw new PathEngineException("The parameter type '"+a+"' is not legal for "+funcName+" parameter "+Integer.toString(i)+". expecting "+pt.toString());
+ throw new PathEngineException("The parameter type '"+a+"' is not legal for "+funcName+" parameter "+Integer.toString(i)+". expecting "+pt.toString(), expr.getStart(), expr.toString());
}
}
}
- private void checkOrdered(TypeDetails focus, String name) throws PathEngineException {
+ private void checkOrdered(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (focus.getCollectionStatus() == CollectionStatus.UNORDERED)
- throw new PathEngineException("The function '"+name+"'() can only be used on ordered collections");
+ throw new PathEngineException("The function '"+name+"'() can only be used on ordered collections", expr.getStart(), expr.toString());
}
- private void checkContextReference(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextReference(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "Reference") && !focus.hasType(worker, "canonical"))
- throw new PathEngineException("The function '"+name+"'() can only be used on string, uri, canonical, Reference");
+ throw new PathEngineException("The function '"+name+"'() can only be used on string, uri, canonical, Reference", expr.getStart(), expr.toString());
}
- private void checkContextCoded(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextCoded(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "Coding") && !focus.hasType(worker, "CodeableConcept"))
- throw new PathEngineException("The function '"+name+"'() can only be used on string, code, uri, Coding, CodeableConcept");
+ throw new PathEngineException("The function '"+name+"'() can only be used on string, code, uri, Coding, CodeableConcept", expr.getStart(), expr.toString());
}
- private void checkContextString(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextString(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "canonical") && !focus.hasType(worker, "id"))
- throw new PathEngineException("The function '"+name+"'() can only be used on string, uri, code, id, but found "+focus.describe());
+ throw new PathEngineException("The function '"+name+"'() can only be used on string, uri, code, id, but found "+focus.describe(), expr.getStart(), expr.toString());
}
- private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty) throws PathEngineException {
+ private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty, ExpressionNode expr) throws PathEngineException {
if (canQty) {
if (!focus.hasType(primitiveTypes) && !focus.hasType("Quantity"))
- throw new PathEngineException("The function '"+name+"'() can only be used on a Quantity or on "+primitiveTypes.toString());
+ throw new PathEngineException("The function '"+name+"'() can only be used on a Quantity or on "+primitiveTypes.toString(), expr.getStart(), expr.toString());
} else if (!focus.hasType(primitiveTypes))
- throw new PathEngineException("The function '"+name+"'() can only be used on "+primitiveTypes.toString());
+ throw new PathEngineException("The function '"+name+"'() can only be used on "+primitiveTypes.toString(), expr.getStart(), expr.toString());
}
- private TypeDetails childTypes(TypeDetails focus, String mask) throws PathEngineException, DefinitionException {
+ private TypeDetails childTypes(TypeDetails focus, String mask, ExpressionNode expr) throws PathEngineException, DefinitionException {
TypeDetails result = new TypeDetails(CollectionStatus.UNORDERED);
for (String f : focus.getTypes())
- getChildTypesByName(f, mask, result);
+ getChildTypesByName(f, mask, result, expr);
return result;
}
@@ -2895,7 +2896,7 @@ public class FHIRPathEngine {
for (Base item : focus) {
pc.clear();
pc.add(item);
- Equality eq = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true));
+ Equality eq = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true), exp);
if (eq != Equality.True) {
all = false;
break;
@@ -2990,15 +2991,15 @@ public class FHIRPathEngine {
result.add(new StringType(n));
}
else {
- throw new PathEngineException(String.format("funcReplace() : checking for 2 arguments (pattern, substitution) but found %d items", exp.getParameters().size()));
+ throw new PathEngineException(String.format("funcReplace() : checking for 2 arguments (pattern, substitution) but found %d items", exp.getParameters().size()), exp.getStart(), exp.toString());
}
}
else {
- throw new PathEngineException(String.format("funcReplace() : checking for 1 string item but found empty item"));
+ throw new PathEngineException(String.format("funcReplace() : checking for 1 string item but found empty item"), exp.getStart(), exp.toString());
}
}
else {
- throw new PathEngineException(String.format("funcReplace() : checking for 1 string item but found %d items", focus.size()));
+ throw new PathEngineException(String.format("funcReplace() : checking for 1 string item but found %d items", focus.size()), exp.getStart(), exp.toString());
}
return result;
}
@@ -3115,7 +3116,7 @@ public class FHIRPathEngine {
private List funcIif(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException {
List n1 = execute(context, focus, exp.getParameters().get(0), true);
- Equality v = asBool(n1);
+ Equality v = asBool(n1, exp);
if (v == Equality.True)
return execute(context, focus, exp.getParameters().get(1), true);
@@ -3187,7 +3188,7 @@ public class FHIRPathEngine {
private List funcSingle(ExecutionContext context, List focus, ExpressionNode exp) throws PathEngineException {
if (focus.size() == 1)
return focus;
- throw new PathEngineException(String.format("Single() : checking for 1 item but found %d items", focus.size()));
+ throw new PathEngineException(String.format("Single() : checking for 1 item but found %d items", focus.size()), exp.getStart(), exp.toString());
}
@@ -3199,10 +3200,10 @@ public class FHIRPathEngine {
ExpressionNode texp = exp.getParameters().get(0);
if (texp.getKind() != Kind.Name)
- throw new PathEngineException("Unsupported Expression type for Parameter on Is");
+ throw new PathEngineException("Unsupported Expression type for Parameter on Is", exp.getStart(), exp.toString());
if (texp.getInner() != null) {
if (texp.getInner().getKind() != Kind.Name)
- throw new PathEngineException("Unsupported Expression type for Parameter on Is");
+ throw new PathEngineException("Unsupported Expression type for Parameter on Is", exp.getStart(), exp.toString());
ns = texp.getName();
n = texp.getInner().getName();
} else if (Utilities.existsInList(texp.getName(), "Boolean", "Integer", "Decimal", "String", "DateTime", "Time", "SimpleTypeInfo", "ClassInfo")) {
@@ -3447,7 +3448,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v != Equality.False) {
all = false;
break;
@@ -3477,7 +3478,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v == Equality.False) {
any = true;
break;
@@ -3507,7 +3508,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v != Equality.True) {
all = false;
break;
@@ -3537,7 +3538,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v == Equality.True) {
any = true;
break;
@@ -3961,7 +3962,7 @@ public class FHIRPathEngine {
for (Base item : focus) {
pc.clear();
pc.add(item);
- Equality v = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true));
+ Equality v = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true), exp);
if (v == Equality.True)
result.add(item);
}
@@ -3996,7 +3997,7 @@ public class FHIRPathEngine {
private List funcNot(ExecutionContext context, List focus, ExpressionNode exp) throws PathEngineException {
List result = new ArrayList();
- Equality v = asBool(focus);
+ Equality v = asBool(focus, exp);
if (v != Equality.Null)
result.add(new BooleanType(v != Equality.True));
return result;
@@ -4019,9 +4020,9 @@ public class FHIRPathEngine {
}
- private void getChildTypesByName(String type, String name, TypeDetails result) throws PathEngineException, DefinitionException {
+ private void getChildTypesByName(String type, String name, TypeDetails result, ExpressionNode expr) throws PathEngineException, DefinitionException {
if (Utilities.noString(type))
- throw new PathEngineException("No type provided in BuildToolPathEvaluator.getChildTypesByName");
+ throw new PathEngineException("No type provided in BuildToolPathEvaluator.getChildTypesByName", expr.getStart(), expr.toString());
if (type.equals("http://hl7.org/fhir/StructureDefinition/xhtml"))
return;
if (type.startsWith(Constants.NS_SYSTEM_TYPE))
@@ -4045,7 +4046,7 @@ public class FHIRPathEngine {
List sdl = new ArrayList();
ElementDefinitionMatch m = null;
if (type.contains("#"))
- m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false);
+ m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr);
if (m != null && hasDataType(m.definition)) {
if (m.fixedType != null)
{
@@ -4084,11 +4085,11 @@ public class FHIRPathEngine {
if (t.getCode().equals("Resource")) {
for (String rn : worker.getResourceNames()) {
if (!result.hasType(worker, rn)) {
- getChildTypesByName(result.addType(rn), "**", result);
+ getChildTypesByName(result.addType(rn), "**", result, expr);
}
}
} else if (!result.hasType(worker, tn)) {
- getChildTypesByName(result.addType(tn), "**", result);
+ getChildTypesByName(result.addType(tn), "**", result, expr);
}
}
}
@@ -4111,7 +4112,7 @@ public class FHIRPathEngine {
} else {
path = sdi.getSnapshot().getElement().get(0).getPath()+tail+"."+name;
- ElementDefinitionMatch ed = getElementDefinition(sdi, path, false);
+ ElementDefinitionMatch ed = getElementDefinition(sdi, path, false, expr);
if (ed != null) {
if (!Utilities.noString(ed.getFixedType()))
result.addType(ed.getFixedType());
@@ -4160,7 +4161,7 @@ public class FHIRPathEngine {
}
- private ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName) throws PathEngineException {
+ private ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName, ExpressionNode expr) throws PathEngineException {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().equals(path)) {
if (ed.hasContentReference()) {
@@ -4180,15 +4181,15 @@ public class FHIRPathEngine {
if (ed.getPath().contains(".") && path.startsWith(ed.getPath()+".") && (ed.getType().size() > 0) && !isAbstractType(ed.getType())) {
// now we walk into the type.
if (ed.getType().size() > 1) // if there's more than one type, the test above would fail this
- throw new PathEngineException("Internal typing issue....");
+ throw new PathEngineException("Internal typing issue....", expr.getStart(), expr.toString());
StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), worker.getOverrideVersionNs()));
if (nsd == null)
- throw new PathEngineException("Unknown type "+ed.getType().get(0).getCode());
- return getElementDefinition(nsd, nsd.getId()+path.substring(ed.getPath().length()), allowTypedName);
+ throw new PathEngineException("Unknown type "+ed.getType().get(0).getCode(), expr.getStart(), expr.toString());
+ return getElementDefinition(nsd, nsd.getId()+path.substring(ed.getPath().length()), allowTypedName, expr);
}
if (ed.hasContentReference() && path.startsWith(ed.getPath()+".")) {
ElementDefinitionMatch m = getElementDefinitionById(sd, ed.getContentReference());
- return getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName);
+ return getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
}
}
return null;
@@ -4363,13 +4364,13 @@ public class FHIRPathEngine {
return path.substring(path.lastIndexOf(".") + 1);
}
- private Equality asBool(List items) throws PathEngineException {
+ private Equality asBool(List items, ExpressionNode expr) throws PathEngineException {
if (items.size() == 0)
return Equality.Null;
else if (items.size() == 1)
return asBool(items.get(0));
else
- throw new PathEngineException("Unable to evaluate as a boolean: "+convertToString(items));
+ throw new PathEngineException("Unable to evaluate as a boolean: "+convertToString(items), expr.getStart(), expr.toString());
}
private Equality asBoolFromInt(String s) {
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java
index 3ef89fd7b..253a39b65 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java
@@ -34,6 +34,7 @@ package org.hl7.fhir.r5.model;
import java.util.ArrayList;
import java.util.List;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.Utilities;
public class ExpressionNode {
@@ -41,31 +42,7 @@ public class ExpressionNode {
public enum Kind {
Name, Function, Constant, Group, Unary
}
- public static class SourceLocation {
- private int line;
- private int column;
- public SourceLocation(int line, int column) {
- super();
- this.line = line;
- this.column = column;
- }
- public int getLine() {
- return line;
- }
- public int getColumn() {
- return column;
- }
- public void setLine(int line) {
- this.line = line;
- }
- public void setColumn(int column) {
- this.column = column;
- }
- public String toString() {
- return Integer.toString(line)+", "+Integer.toString(column);
- }
- }
public enum Function {
Custom,
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRLexer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRLexer.java
index e08acbefb..4400bcdc8 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRLexer.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRLexer.java
@@ -34,7 +34,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.ExpressionNode;
-import org.hl7.fhir.r5.model.ExpressionNode.SourceLocation;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.Utilities;
// shared lexer for concrete syntaxes
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java
index 6f6e4de68..334b8648f 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java
@@ -39,7 +39,6 @@ import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
import org.hl7.fhir.r5.model.ExpressionNode.Function;
import org.hl7.fhir.r5.model.ExpressionNode.Kind;
import org.hl7.fhir.r5.model.ExpressionNode.Operation;
-import org.hl7.fhir.r5.model.ExpressionNode.SourceLocation;
import org.hl7.fhir.r5.model.Property.PropertyMatcher;
import org.hl7.fhir.r5.model.IntegerType;
import org.hl7.fhir.r5.model.Property;
@@ -59,6 +58,7 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MergedList;
import org.hl7.fhir.utilities.MergedList.MergeNode;
+import org.hl7.fhir.utilities.SourceLocation;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage;
@@ -510,11 +510,11 @@ public class FHIRPathEngine {
}
StructureDefinition sd = worker.fetchResource(StructureDefinition.class, ctxt);
if (sd == null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, context);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, context);
}
- ElementDefinitionMatch ed = getElementDefinition(sd, context, true);
+ ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
}
if (ed.fixedType != null) {
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
@@ -531,12 +531,16 @@ public class FHIRPathEngine {
return executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, true);
}
- private FHIRException makeException(String constName, Object... args) {
+ private FHIRException makeException(ExpressionNode holder, String constName, Object... args) {
String fmt = worker.formatMessage(constName, args);
if (location != null) {
fmt = fmt + " "+worker.formatMessage(I18nConstants.FHIRPATH_LOCATION, location);
}
- return new PathEngineException(fmt);
+ if (holder != null) {
+ return new PathEngineException(fmt, holder.getStart(), holder.toString());
+ } else {
+ return new PathEngineException(fmt);
+ }
}
public TypeDetails check(Object appContext, StructureDefinition sd, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
@@ -545,9 +549,9 @@ public class FHIRPathEngine {
if (!context.contains(".")) {
types = new TypeDetails(CollectionStatus.SINGLETON, sd.getUrl());
} else {
- ElementDefinitionMatch ed = getElementDefinition(sd, context, true);
+ ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
}
if (ed.fixedType != null) {
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
@@ -908,7 +912,7 @@ public class FHIRPathEngine {
aliases = new HashMap(aliases); // clone it, since it's going to change
}
if (focus.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_ALIAS_COLLECTION);
+ throw makeException(null, I18nConstants.FHIRPATH_ALIAS_COLLECTION);
}
aliases.put(name, focus.size() == 0 ? null : focus.get(0));
}
@@ -957,6 +961,7 @@ public class FHIRPathEngine {
wrapper = new ExpressionNode(lexer.nextId());
wrapper.setKind(Kind.Unary);
wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.take()));
+ wrapper.setStart(lexer.getCurrentLocation());
wrapper.setProximal(proximal);
}
@@ -968,6 +973,7 @@ public class FHIRPathEngine {
wrapper.setKind(Kind.Unary);
wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent().substring(0, 1)));
wrapper.setProximal(proximal);
+ wrapper.setStart(lexer.getCurrentLocation());
lexer.setCurrent(lexer.getCurrent().substring(1));
}
result.setConstant(processConstant(lexer));
@@ -1355,7 +1361,7 @@ public class FHIRPathEngine {
work.addAll(work2);
break;
case Constant:
- Base b = resolveConstant(context, exp.getConstant(), false);
+ Base b = resolveConstant(context, exp.getConstant(), false, exp);
if (b != null) {
work.add(b);
}
@@ -1373,16 +1379,16 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
- List work2 = preOperate(work, last.getOperation());
+ List work2 = preOperate(work, last.getOperation(), exp);
if (work2 != null) {
work = work2;
}
else if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
work2 = executeTypeName(context, focus, next, false);
- work = operate(context, work, last.getOperation(), work2);
+ work = operate(context, work, last.getOperation(), work2, last);
} else {
work2 = execute(context, focus, next, true);
- work = operate(context, work, last.getOperation(), work2);
+ work = operate(context, work, last.getOperation(), work2, last);
// System.out.println("Result of {'"+last.toString()+" "+last.getOperation().toCode()+" "+next.toString()+"'}: "+focus.toString());
}
last = next;
@@ -1404,7 +1410,7 @@ public class FHIRPathEngine {
}
- private List preOperate(List left, Operation operation) throws PathEngineException {
+ private List preOperate(List left, Operation operation, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0) {
return null;
}
@@ -1414,7 +1420,7 @@ public class FHIRPathEngine {
case Or:
return isBoolean(left, true) ? makeBoolean(true) : null;
case Implies:
- Equality v = asBool(left);
+ Equality v = asBool(left, expr);
return v == Equality.False ? makeBoolean(true) : null;
default:
return null;
@@ -1445,13 +1451,13 @@ public class FHIRPathEngine {
} else if (atEntry && exp.getName().equals("$total")) {
result.update(anything(CollectionStatus.UNORDERED));
} else if (atEntry && focus == null) {
- result.update(executeContextType(context, exp.getName()));
+ result.update(executeContextType(context, exp.getName(), exp));
} else {
for (String s : focus.getTypes()) {
result.update(executeType(s, exp, atEntry));
}
if (result.hasNoTypes()) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_NAME, exp.getName(), focus.describe());
+ throw makeException(exp, I18nConstants.FHIRPATH_UNKNOWN_NAME, exp.getName(), focus.describe());
}
}
break;
@@ -1464,7 +1470,7 @@ public class FHIRPathEngine {
result.addType(TypeDetails.FP_Quantity);
break;
case Constant:
- result.update(resolveConstantType(context, exp.getConstant()));
+ result.update(resolveConstantType(context, exp.getConstant(), exp));
break;
case Group:
result.update(executeType(context, focus, exp.getGroup(), atEntry));
@@ -1485,7 +1491,7 @@ public class FHIRPathEngine {
} else {
work = executeType(context, focus, next, atEntry);
}
- result = operateTypes(result, last.getOperation(), work);
+ result = operateTypes(result, last.getOperation(), work, last);
last = next;
next = next.getOpNext();
}
@@ -1494,21 +1500,21 @@ public class FHIRPathEngine {
return result;
}
- private Base resolveConstant(ExecutionContext context, Base constant, boolean beforeContext) throws PathEngineException {
+ private Base resolveConstant(ExecutionContext context, Base constant, boolean beforeContext, ExpressionNode expr) throws PathEngineException {
if (!(constant instanceof FHIRConstant)) {
return constant;
}
FHIRConstant c = (FHIRConstant) constant;
if (c.getValue().startsWith("%")) {
- return resolveConstant(context, c.getValue(), beforeContext);
+ return resolveConstant(context, c.getValue(), beforeContext, expr);
} else if (c.getValue().startsWith("@")) {
- return processDateConstant(context.appInfo, c.getValue().substring(1));
+ return processDateConstant(context.appInfo, c.getValue().substring(1), expr);
} else {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, c.getValue());
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, c.getValue());
}
}
- private Base processDateConstant(Object appInfo, String value) throws PathEngineException {
+ private Base processDateConstant(Object appInfo, String value, ExpressionNode expr) throws PathEngineException {
String date = null;
String time = null;
String tz = null;
@@ -1556,7 +1562,7 @@ public class FHIRPathEngine {
if (date == null) {
if (tz != null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, value);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, value);
} else {
TimeType tt = new TimeType(time);
tt.setPrecision(temp);
@@ -1572,7 +1578,7 @@ public class FHIRPathEngine {
}
- private Base resolveConstant(ExecutionContext context, String s, boolean beforeContext) throws PathEngineException {
+ private Base resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr) throws PathEngineException {
if (s.equals("%sct")) {
return new StringType("http://snomed.info/sct").noExtensions();
} else if (s.equals("%loinc")) {
@@ -1581,12 +1587,12 @@ public class FHIRPathEngine {
return new StringType("http://unitsofmeasure.org").noExtensions();
} else if (s.equals("%resource")) {
if (context.focusResource == null) {
- throw makeException(I18nConstants.FHIRPATH_CANNOT_USE, "%resource", "no focus resource");
+ throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%resource", "no focus resource");
}
return context.focusResource;
} else if (s.equals("%rootResource")) {
if (context.rootResource == null) {
- throw makeException(I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus resource");
+ throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus resource");
}
return context.rootResource;
} else if (s.equals("%context")) {
@@ -1600,7 +1606,7 @@ public class FHIRPathEngine {
} else if (s.startsWith("%`ext-")) {
return new StringType("http://hl7.org/fhir/StructureDefinition/"+s.substring(6, s.length()-1)).noExtensions();
} else if (hostServices == null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
} else {
return hostServices.resolveConstant(context.appInfo, s.substring(1), beforeContext);
}
@@ -1661,39 +1667,39 @@ public class FHIRPathEngine {
}
- private List operate(ExecutionContext context, List left, Operation operation, List right) throws FHIRException {
+ private List operate(ExecutionContext context, List left, Operation operation, List right, ExpressionNode holder) throws FHIRException {
switch (operation) {
- case Equals: return opEquals(left, right);
- case Equivalent: return opEquivalent(left, right);
- case NotEquals: return opNotEquals(left, right);
- case NotEquivalent: return opNotEquivalent(left, right);
- case LessThan: return opLessThan(left, right);
- case Greater: return opGreater(left, right);
- case LessOrEqual: return opLessOrEqual(left, right);
- case GreaterOrEqual: return opGreaterOrEqual(left, right);
- case Union: return opUnion(left, right);
- case In: return opIn(left, right);
- case MemberOf: return opMemberOf(context, left, right);
- case Contains: return opContains(left, right);
- case Or: return opOr(left, right);
- case And: return opAnd(left, right);
- case Xor: return opXor(left, right);
- case Implies: return opImplies(left, right);
- case Plus: return opPlus(left, right);
- case Times: return opTimes(left, right);
- case Minus: return opMinus(left, right);
- case Concatenate: return opConcatenate(left, right);
- case DivideBy: return opDivideBy(left, right);
- case Div: return opDiv(left, right);
- case Mod: return opMod(left, right);
- case Is: return opIs(left, right);
- case As: return opAs(left, right);
+ case Equals: return opEquals(left, right, holder);
+ case Equivalent: return opEquivalent(left, right, holder);
+ case NotEquals: return opNotEquals(left, right, holder);
+ case NotEquivalent: return opNotEquivalent(left, right, holder);
+ case LessThan: return opLessThan(left, right, holder);
+ case Greater: return opGreater(left, right, holder);
+ case LessOrEqual: return opLessOrEqual(left, right, holder);
+ case GreaterOrEqual: return opGreaterOrEqual(left, right, holder);
+ case Union: return opUnion(left, right, holder);
+ case In: return opIn(left, right, holder);
+ case MemberOf: return opMemberOf(context, left, right, holder);
+ case Contains: return opContains(left, right, holder);
+ case Or: return opOr(left, right, holder);
+ case And: return opAnd(left, right, holder);
+ case Xor: return opXor(left, right, holder);
+ case Implies: return opImplies(left, right, holder);
+ case Plus: return opPlus(left, right, holder);
+ case Times: return opTimes(left, right, holder);
+ case Minus: return opMinus(left, right, holder);
+ case Concatenate: return opConcatenate(left, right, holder);
+ case DivideBy: return opDivideBy(left, right, holder);
+ case Div: return opDiv(left, right, holder);
+ case Mod: return opMod(left, right, holder);
+ case Is: return opIs(left, right, holder);
+ case As: return opAs(left, right, holder);
default:
throw new Error("Not Done Yet: "+operation.toCode());
}
}
- private List opAs(List left, List right) {
+ private List opAs(List left, List right, ExpressionNode expr) {
List result = new ArrayList<>();
if (right.size() != 1) {
return result;
@@ -1709,7 +1715,7 @@ public class FHIRPathEngine {
}
- private List opIs(List left, List right) {
+ private List opIs(List left, List right, ExpressionNode expr) {
List result = new ArrayList();
if (left.size() == 0 || right.size() == 0) {
} else if (left.size() != 1 || right.size() != 1)
@@ -1728,7 +1734,7 @@ public class FHIRPathEngine {
}
- private TypeDetails operateTypes(TypeDetails left, Operation operation, TypeDetails right) {
+ private TypeDetails operateTypes(TypeDetails left, Operation operation, TypeDetails right, ExpressionNode expr) {
switch (operation) {
case Equals: return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Equivalent: return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
@@ -1776,7 +1782,7 @@ public class FHIRPathEngine {
if (right.hasType(worker, "Quantity")) {
result.addType(left.getType());
} else {
- throw new PathEngineException(String.format("Error in date arithmetic: Unable to add type {0} to {1}", right.getType(), left.getType()));
+ throw new PathEngineException(String.format("Error in date arithmetic: Unable to add type {0} to {1}", right.getType(), left.getType()), expr.getOpStart(), expr.toString());
}
}
return result;
@@ -1814,7 +1820,7 @@ public class FHIRPathEngine {
}
- private List opEquals(List left, List right) {
+ private List opEquals(List left, List right, ExpressionNode expr) {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
@@ -1843,7 +1849,7 @@ public class FHIRPathEngine {
}
}
- private List opNotEquals(List left, List right) {
+ private List opNotEquals(List left, List right, ExpressionNode expr) {
if (!legacyMode && (left.size() == 0 || right.size() == 0)) {
return new ArrayList();
}
@@ -2074,7 +2080,7 @@ public class FHIRPathEngine {
- private List opEquivalent(List left, List right) throws PathEngineException {
+ private List opEquivalent(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() != right.size()) {
return makeBoolean(false);
}
@@ -2096,7 +2102,7 @@ public class FHIRPathEngine {
return makeBoolean(res);
}
- private List opNotEquivalent(List left, List right) throws PathEngineException {
+ private List opNotEquivalent(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() != right.size()) {
return makeBoolean(true);
}
@@ -2120,7 +2126,7 @@ public class FHIRPathEngine {
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary", "canonical", "url"};
- private List opLessThan(List left, List right) throws FHIRException {
+ private List opLessThan(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
@@ -2146,13 +2152,13 @@ public class FHIRPathEngine {
return makeBoolean(i < 0);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
}
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("code");
List rUnit = right.get(0).listChildrenByName("code");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opLessThan(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opLessThan(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null) {
return makeBoolean(false);
@@ -2161,14 +2167,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
- return opLessThan(dl, dr);
+ return opLessThan(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opGreater(List left, List right) throws FHIRException {
+ private List opGreater(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
return new ArrayList();
if (left.size() == 1 && right.size() == 1 && left.get(0).isPrimitive() && right.get(0).isPrimitive()) {
@@ -2193,13 +2199,13 @@ public class FHIRPathEngine {
return makeBoolean(i > 0);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
}
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("unit");
List rUnit = right.get(0).listChildrenByName("unit");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opGreater(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opGreater(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null) {
return makeBoolean(false);
@@ -2208,14 +2214,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
- return opGreater(dl, dr);
+ return opGreater(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opLessOrEqual(List left, List right) throws FHIRException {
+ private List opLessOrEqual(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
@@ -2241,7 +2247,7 @@ public class FHIRPathEngine {
return makeBoolean(i <= 0);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
}
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnits = left.get(0).listChildrenByName("unit");
@@ -2249,7 +2255,7 @@ public class FHIRPathEngine {
List rUnits = right.get(0).listChildrenByName("unit");
String runit = rUnits.size() == 1 ? rUnits.get(0).primitiveValue() : null;
if ((lunit == null && runit == null) || lunit.equals(runit)) {
- return opLessOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opLessOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null) {
return makeBoolean(false);
@@ -2258,14 +2264,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
- return opLessOrEqual(dl, dr);
+ return opLessOrEqual(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opGreaterOrEqual(List left, List right) throws FHIRException {
+ private List opGreaterOrEqual(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
@@ -2291,13 +2297,13 @@ public class FHIRPathEngine {
return makeBoolean(i >= 0);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_CANT_COMPARE, l.fhirType(), r.fhirType());
}
} else if (left.size() == 1 && right.size() == 1 && left.get(0).fhirType().equals("Quantity") && right.get(0).fhirType().equals("Quantity") ) {
List lUnit = left.get(0).listChildrenByName("unit");
List rUnit = right.get(0).listChildrenByName("unit");
if (Base.compareDeep(lUnit, rUnit, true)) {
- return opGreaterOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"));
+ return opGreaterOrEqual(left.get(0).listChildrenByName("value"), right.get(0).listChildrenByName("value"), expr);
} else {
if (worker.getUcumService() == null) {
return makeBoolean(false);
@@ -2306,14 +2312,14 @@ public class FHIRPathEngine {
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
List dr = new ArrayList();
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
- return opGreaterOrEqual(dl, dr);
+ return opGreaterOrEqual(dl, dr, expr);
}
}
}
return new ArrayList();
}
- private List opMemberOf(ExecutionContext context, List left, List right) throws FHIRException {
+ private List opMemberOf(ExecutionContext context, List left, List right, ExpressionNode expr) throws FHIRException {
boolean ans = false;
ValueSet vs = hostServices != null ? hostServices.resolveValueSet(context.appInfo, right.get(0).primitiveValue()) : worker.fetchResource(ValueSet.class, right.get(0).primitiveValue());
if (vs != null) {
@@ -2338,7 +2344,7 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opIn(List left, List right) throws FHIRException {
+ private List opIn(List left, List right, ExpressionNode expr) throws FHIRException {
if (left.size() == 0) {
return new ArrayList();
}
@@ -2363,7 +2369,7 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opContains(List left, List right) {
+ private List opContains(List left, List right, ExpressionNode expr) {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
@@ -2385,21 +2391,21 @@ public class FHIRPathEngine {
return makeBoolean(ans);
}
- private List opPlus(List left, List right) throws PathEngineException {
+ private List opPlus(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "+");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "+");
}
if (!left.get(0).isPrimitive()) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "+", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "+", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "+");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "+");
}
if (!right.get(0).isPrimitive() && !((left.get(0).isDateTime() || "0".equals(left.get(0).primitiveValue()) || left.get(0).hasType("Quantity")) && right.get(0).hasType("Quantity"))) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "+", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "+", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2412,14 +2418,14 @@ public class FHIRPathEngine {
} else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer")) {
result.add(new DecimalType(new BigDecimal(l.primitiveValue()).add(new BigDecimal(r.primitiveValue()))));
} else if (l.isDateTime() && r.hasType("Quantity")) {
- result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, false));
+ result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, false, expr));
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "+", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "+", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private BaseDateTimeType dateAdd(BaseDateTimeType d, Quantity q, boolean negate) {
+ private BaseDateTimeType dateAdd(BaseDateTimeType d, Quantity q, boolean negate, ExpressionNode holder) {
BaseDateTimeType result = (BaseDateTimeType) d.copy();
int value = negate ? 0 - q.getValue().intValue() : q.getValue().intValue();
@@ -2435,7 +2441,7 @@ public class FHIRPathEngine {
result.add(Calendar.MONTH, value);
break;
case "mo":
- throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()));
+ throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()), holder.getOpStart(), holder.toString());
case "weeks":
case "week":
case "wk":
@@ -2472,21 +2478,21 @@ public class FHIRPathEngine {
return result;
}
- private List opTimes(List left, List right) throws PathEngineException {
+ private List opTimes(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "*");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "*");
}
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "*", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "*", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "*");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "*");
}
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "*", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "*", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2505,27 +2511,27 @@ public class FHIRPathEngine {
p = worker.getUcumService().multiply(pl, pr);
result.add(pairToQty(p));
} catch (UcumException e) {
- throw new PathEngineException(e.getMessage(), e);
+ throw new PathEngineException(e.getMessage(), expr.getOpStart(), expr.toString(), e);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "*", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "*", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private List opConcatenate(List left, List right) throws PathEngineException {
+ private List opConcatenate(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "&");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "&");
}
if (left.size() > 0 && !left.get(0).hasType(FHIR_TYPES_STRING)) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "&", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "&", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "&");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "&");
}
if (right.size() > 0 && !right.get(0).hasType(FHIR_TYPES_STRING)) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "&", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "&", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2535,7 +2541,7 @@ public class FHIRPathEngine {
return result;
}
- private List opUnion(List left, List right) {
+ private List opUnion(List left, List right, ExpressionNode expr) {
List result = new ArrayList();
for (Base item : left) {
if (!doContains(result, item)) {
@@ -2561,9 +2567,9 @@ public class FHIRPathEngine {
}
- private List opAnd(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opAnd(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case False: return makeBoolean(false);
case Null:
@@ -2586,9 +2592,9 @@ public class FHIRPathEngine {
return list.size() == 1 && list.get(0) instanceof BooleanType && ((BooleanType) list.get(0)).booleanValue() == b;
}
- private List opOr(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opOr(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case True: return makeBoolean(true);
case Null:
@@ -2607,9 +2613,9 @@ public class FHIRPathEngine {
return makeNull();
}
- private List opXor(List left, List right) throws PathEngineException {
- Equality l = asBool(left);
- Equality r = asBool(right);
+ private List opXor(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality l = asBool(left, expr);
+ Equality r = asBool(right, expr);
switch (l) {
case True:
switch (r) {
@@ -2629,13 +2635,13 @@ public class FHIRPathEngine {
return makeNull();
}
- private List opImplies(List left, List right) throws PathEngineException {
- Equality eq = asBool(left);
+ private List opImplies(List left, List right, ExpressionNode expr) throws PathEngineException {
+ Equality eq = asBool(left, expr);
if (eq == Equality.False) {
return makeBoolean(true);
} else if (right.size() == 0) {
return makeNull();
- } else switch (asBool(right)) {
+ } else switch (asBool(right, expr)) {
case False: return eq == Equality.Null ? makeNull() : makeBoolean(false);
case Null: return makeNull();
case True: return makeBoolean(true);
@@ -2644,21 +2650,21 @@ public class FHIRPathEngine {
}
- private List opMinus(List left, List right) throws PathEngineException {
+ private List opMinus(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "-");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "-");
}
if (!left.get(0).isPrimitive() && !left.get(0).hasType("Quantity")) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "-", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "-", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "-");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "-");
}
if (!right.get(0).isPrimitive() && !((left.get(0).isDateTime() || "0".equals(left.get(0).primitiveValue()) || left.get(0).hasType("Quantity")) && right.get(0).hasType("Quantity"))) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "-", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "-", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2676,28 +2682,28 @@ public class FHIRPathEngine {
result.add(qty.copy().setValue(qty.getValue().abs()));
}
} else if (l.isDateTime() && r.hasType("Quantity")) {
- result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, true));
+ result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, true, expr));
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "-", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "-", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private List opDivideBy(List left, List right) throws PathEngineException {
+ private List opDivideBy(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "/");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "/");
}
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "/", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "/", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "/");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "/");
}
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "/", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "/", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2724,26 +2730,26 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "/", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "/", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private List opDiv(List left, List right) throws PathEngineException {
+ private List opDiv(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
}
if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "div");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "div");
}
if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "div", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "div", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "div");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "div");
}
if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity)) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "div", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "div", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2765,25 +2771,25 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "div", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "div", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private List opMod(List left, List right) throws PathEngineException {
+ private List opMod(List left, List right, ExpressionNode expr) throws PathEngineException {
if (left.size() == 0 || right.size() == 0) {
return new ArrayList();
} if (left.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "mod");
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "mod");
}
if (!left.get(0).isPrimitive()) {
- throw makeException(I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "mod", left.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "mod", left.get(0).fhirType());
}
if (right.size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "mod");
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "mod");
}
if (!right.get(0).isPrimitive()) {
- throw makeException(I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "mod", right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "mod", right.get(0).fhirType());
}
List result = new ArrayList();
@@ -2805,13 +2811,13 @@ public class FHIRPathEngine {
throw new PathEngineException(e);
}
} else {
- throw makeException(I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "mod", left.get(0).fhirType(), right.get(0).fhirType());
+ throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "mod", left.get(0).fhirType(), right.get(0).fhirType());
}
return result;
}
- private TypeDetails resolveConstantType(ExecutionTypeContext context, Base constant) throws PathEngineException {
+ private TypeDetails resolveConstantType(ExecutionTypeContext context, Base constant, ExpressionNode expr) throws PathEngineException {
if (constant instanceof BooleanType) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
} else if (constant instanceof IntegerType) {
@@ -2821,13 +2827,13 @@ public class FHIRPathEngine {
} else if (constant instanceof Quantity) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Quantity);
} else if (constant instanceof FHIRConstant) {
- return resolveConstantType(context, ((FHIRConstant) constant).getValue());
+ return resolveConstantType(context, ((FHIRConstant) constant).getValue(), expr);
} else {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
}
- private TypeDetails resolveConstantType(ExecutionTypeContext context, String s) throws PathEngineException {
+ private TypeDetails resolveConstantType(ExecutionTypeContext context, String s, ExpressionNode expr) throws PathEngineException {
if (s.startsWith("@")) {
if (s.startsWith("@T")) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time);
@@ -2842,12 +2848,12 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
} else if (s.equals("%resource")) {
if (context.resource == null) {
- throw makeException(I18nConstants.FHIRPATH_CANNOT_USE, "%resource", "no focus resource");
+ throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%resource", "no focus resource");
}
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
} else if (s.equals("%rootResource")) {
if (context.resource == null) {
- throw makeException(I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus resource");
+ throw makeException(expr, I18nConstants.FHIRPATH_CANNOT_USE, "%rootResource", "no focus resource");
}
return new TypeDetails(CollectionStatus.SINGLETON, context.resource);
} else if (s.equals("%context")) {
@@ -2863,7 +2869,7 @@ public class FHIRPathEngine {
} else if (s.startsWith("%`ext-")) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
} else if (hostServices == null) {
- throw makeException(I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
+ throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
} else {
return hostServices.resolveConstantType(context.appInfo, s);
}
@@ -2914,9 +2920,9 @@ public class FHIRPathEngine {
}
- private TypeDetails executeContextType(ExecutionTypeContext context, String name) throws PathEngineException, DefinitionException {
+ private TypeDetails executeContextType(ExecutionTypeContext context, String name, ExpressionNode expr) throws PathEngineException, DefinitionException {
if (hostServices == null) {
- throw makeException(I18nConstants.FHIRPATH_HO_HOST_SERVICES, "Context Reference");
+ throw makeException(expr, I18nConstants.FHIRPATH_HO_HOST_SERVICES, "Context Reference");
}
return hostServices.resolveConstantType(context.appInfo, name);
}
@@ -2926,7 +2932,7 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, type);
}
TypeDetails result = new TypeDetails(null);
- getChildTypesByName(type, exp.getName(), result);
+ getChildTypesByName(type, exp.getName(), result, exp);
return result;
}
@@ -2956,15 +2962,15 @@ public class FHIRPathEngine {
case Not :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Exists : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case SubsetOf : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, focus);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, focus);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case SupersetOf : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, focus);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, focus);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case IsDistinct :
@@ -2984,16 +2990,16 @@ public class FHIRPathEngine {
case Aggregate :
return anything(focus.getCollectionStatus());
case Item : {
- checkOrdered(focus, "item");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "item", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case As : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName());
}
case OfType : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName());
}
case Type : {
@@ -3012,31 +3018,31 @@ public class FHIRPathEngine {
}
}
case Is : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Single :
return focus.toSingleton();
case First : {
- checkOrdered(focus, "first");
+ checkOrdered(focus, "first", exp);
return focus.toSingleton();
}
case Last : {
- checkOrdered(focus, "last");
+ checkOrdered(focus, "last", exp);
return focus.toSingleton();
}
case Tail : {
- checkOrdered(focus, "tail");
+ checkOrdered(focus, "tail", exp);
return focus;
}
case Skip : {
- checkOrdered(focus, "skip");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "skip", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case Take : {
- checkOrdered(focus, "take");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkOrdered(focus, "take", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return focus;
}
case Union : {
@@ -3060,76 +3066,76 @@ public class FHIRPathEngine {
return types;
}
case Lower : {
- checkContextString(focus, "lower");
+ checkContextString(focus, "lower", exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Upper : {
- checkContextString(focus, "upper");
+ checkContextString(focus, "upper", exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case ToChars : {
- checkContextString(focus, "toChars");
+ checkContextString(focus, "toChars", exp);
return new TypeDetails(CollectionStatus.ORDERED, TypeDetails.FP_String);
}
case IndexOf : {
- checkContextString(focus, "indexOf");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "indexOf", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case Substring : {
- checkContextString(focus, "subString");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkContextString(focus, "subString", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case StartsWith : {
- checkContextString(focus, "startsWith");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "startsWith", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case EndsWith : {
- checkContextString(focus, "endsWith");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "endsWith", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Matches : {
- checkContextString(focus, "matches");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "matches", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ReplaceMatches : {
- checkContextString(focus, "replaceMatches");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "replaceMatches", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Contains : {
- checkContextString(focus, "contains");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "contains", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Replace : {
- checkContextString(focus, "replace");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, "string"), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextString(focus, "replace", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, "string"), new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case Length : {
- checkContextPrimitive(focus, "length", false);
+ checkContextPrimitive(focus, "length", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case Children :
- return childTypes(focus, "*");
+ return childTypes(focus, "*", exp);
case Descendants :
- return childTypes(focus, "**");
+ return childTypes(focus, "**", exp);
case MemberOf : {
- checkContextCoded(focus, "memberOf");
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkContextCoded(focus, "memberOf", exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Trace : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case Check : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case Today :
@@ -3137,11 +3143,11 @@ public class FHIRPathEngine {
case Now :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
case Resolve : {
- checkContextReference(focus, "resolve");
+ checkContextReference(focus, "resolve", exp);
return new TypeDetails(CollectionStatus.SINGLETON, "DomainResource");
}
case Extension : {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, "Extension");
}
case AnyTrue:
@@ -3159,62 +3165,62 @@ public class FHIRPathEngine {
case HtmlChecks2 :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias :
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
case AliasAs :
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
case Encode:
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Decode:
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Escape:
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, 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));
+ checkParamTypes(exp, 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:
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case Join:
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
case ToInteger : {
- checkContextPrimitive(focus, "toInteger", true);
+ checkContextPrimitive(focus, "toInteger", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case ToDecimal : {
- checkContextPrimitive(focus, "toDecimal", true);
+ checkContextPrimitive(focus, "toDecimal", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
}
case ToString : {
- checkContextPrimitive(focus, "toString", true);
+ checkContextPrimitive(focus, "toString", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
}
case ToQuantity : {
- checkContextPrimitive(focus, "toQuantity", true);
+ checkContextPrimitive(focus, "toQuantity", true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Quantity);
}
case ToBoolean : {
- checkContextPrimitive(focus, "toBoolean", false);
+ checkContextPrimitive(focus, "toBoolean", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ToDateTime : {
- checkContextPrimitive(focus, "ToDateTime", false);
+ checkContextPrimitive(focus, "ToDateTime", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
}
case ToTime : {
- checkContextPrimitive(focus, "ToTime", false);
+ checkContextPrimitive(focus, "ToTime", false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time);
}
case ConvertsToString :
case ConvertsToQuantity :{
- checkContextPrimitive(focus, exp.getFunction().toCode(), true);
+ checkContextPrimitive(focus, exp.getFunction().toCode(), true, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ConvertsToInteger :
@@ -3223,28 +3229,28 @@ public class FHIRPathEngine {
case ConvertsToDate :
case ConvertsToTime :
case ConvertsToBoolean : {
- checkContextPrimitive(focus, exp.getFunction().toCode(), false);
+ checkContextPrimitive(focus, exp.getFunction().toCode(), false, exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case ConformsTo: {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
}
case Abs : {
- checkContextNumerical(focus, "abs");
+ checkContextNumerical(focus, "abs", exp);
return new TypeDetails(CollectionStatus.SINGLETON, focus.getTypes());
}
case Truncate :
case Floor :
case Ceiling : {
- checkContextDecimal(focus, exp.getFunction().toCode());
+ checkContextDecimal(focus, exp.getFunction().toCode(), exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
}
case Round :{
- checkContextDecimal(focus, "round");
+ checkContextDecimal(focus, "round", exp);
if (paramTypes.size() > 0) {
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
}
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
}
@@ -3252,17 +3258,17 @@ public class FHIRPathEngine {
case Exp :
case Ln :
case Sqrt : {
- checkContextNumerical(focus, exp.getFunction().toCode());
+ checkContextNumerical(focus, exp.getFunction().toCode(), exp);
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
}
case Log : {
- checkContextNumerical(focus, exp.getFunction().toCode());
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_NUMBERS));
+ checkContextNumerical(focus, exp.getFunction().toCode(), exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_NUMBERS));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
}
case Power : {
- checkContextNumerical(focus, exp.getFunction().toCode());
- checkParamTypes(exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_NUMBERS));
+ checkContextNumerical(focus, exp.getFunction().toCode(), exp);
+ checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_NUMBERS));
return new TypeDetails(CollectionStatus.SINGLETON, focus.getTypes());
}
@@ -3276,7 +3282,7 @@ public class FHIRPathEngine {
}
- private void checkParamTypes(String funcName, List paramTypes, TypeDetails... typeSet) throws PathEngineException {
+ private void checkParamTypes(ExpressionNode expr, String funcName, List paramTypes, TypeDetails... typeSet) throws PathEngineException {
int i = 0;
for (TypeDetails pt : typeSet) {
if (i == paramTypes.size()) {
@@ -3286,65 +3292,65 @@ public class FHIRPathEngine {
i++;
for (String a : actual.getTypes()) {
if (!pt.hasType(worker, a)) {
- throw makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, funcName, i, a, pt.toString());
+ throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, funcName, i, a, pt.toString());
}
}
}
}
- private void checkOrdered(TypeDetails focus, String name) throws PathEngineException {
+ private void checkOrdered(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (focus.getCollectionStatus() == CollectionStatus.UNORDERED) {
- throw makeException(I18nConstants.FHIRPATH_ORDERED_ONLY, name);
+ throw makeException(expr, I18nConstants.FHIRPATH_ORDERED_ONLY, name);
}
}
- private void checkContextReference(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextReference(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "Reference") && !focus.hasType(worker, "canonical")) {
- throw makeException(I18nConstants.FHIRPATH_REFERENCE_ONLY, name, focus.describe());
+ throw makeException(expr, I18nConstants.FHIRPATH_REFERENCE_ONLY, name, focus.describe());
}
}
- private void checkContextCoded(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextCoded(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "Coding") && !focus.hasType(worker, "CodeableConcept")) {
- throw makeException(I18nConstants.FHIRPATH_CODED_ONLY, name, focus.describe());
+ throw makeException(expr, I18nConstants.FHIRPATH_CODED_ONLY, name, focus.describe());
}
}
- private void checkContextString(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextString(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "canonical") && !focus.hasType(worker, "id")) {
- throw makeException(I18nConstants.FHIRPATH_STRING_ONLY, name, focus.describe());
+ throw makeException(expr, I18nConstants.FHIRPATH_STRING_ONLY, name, focus.describe());
}
}
- private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty) throws PathEngineException {
+ private void checkContextPrimitive(TypeDetails focus, String name, boolean canQty, ExpressionNode expr) throws PathEngineException {
if (canQty) {
if (!focus.hasType(primitiveTypes) && !focus.hasType("Quantity")) {
- throw makeException(I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), "Quantity, "+primitiveTypes.toString());
+ throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), "Quantity, "+primitiveTypes.toString());
}
} else if (!focus.hasType(primitiveTypes)) {
- throw makeException(I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), primitiveTypes.toString());
+ throw makeException(expr, I18nConstants.FHIRPATH_PRIMITIVE_ONLY, name, focus.describe(), primitiveTypes.toString());
}
}
- private void checkContextNumerical(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextNumerical(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType("integer") && !focus.hasType("decimal") && !focus.hasType("Quantity")) {
- throw makeException(I18nConstants.FHIRPATH_NUMERICAL_ONLY, name, focus.describe());
+ throw makeException(expr, I18nConstants.FHIRPATH_NUMERICAL_ONLY, name, focus.describe());
}
}
- private void checkContextDecimal(TypeDetails focus, String name) throws PathEngineException {
+ private void checkContextDecimal(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
if (!focus.hasType("decimal") && !focus.hasType("integer")) {
- throw makeException(I18nConstants.FHIRPATH_DECIMAL_ONLY, name, focus.describe());
+ throw makeException(expr, I18nConstants.FHIRPATH_DECIMAL_ONLY, name, focus.describe());
}
}
- private TypeDetails childTypes(TypeDetails focus, String mask) throws PathEngineException, DefinitionException {
+ private TypeDetails childTypes(TypeDetails focus, String mask, ExpressionNode expr) throws PathEngineException, DefinitionException {
TypeDetails result = new TypeDetails(CollectionStatus.UNORDERED);
for (String f : focus.getTypes()) {
- getChildTypesByName(f, mask, result);
+ getChildTypesByName(f, mask, result, expr);
}
return result;
}
@@ -3464,9 +3470,9 @@ public class FHIRPathEngine {
}
}
- private List funcSqrt(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcSqrt(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "sqrt", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "sqrt", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3478,15 +3484,15 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcAbs(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcAbs(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "abs", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "abs", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3501,15 +3507,15 @@ public class FHIRPathEngine {
Quantity qty = (Quantity) base;
result.add(qty.copy().setValue(qty.getValue().abs()));
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "abs", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "abs", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcCeiling(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcCeiling(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "ceiling", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "ceiling", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3520,14 +3526,14 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ceiling", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ceiling", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcFloor(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcFloor(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "floor", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "floor", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3539,15 +3545,15 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "floor", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "floor", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcExp(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcExp(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "exp", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "exp", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3560,15 +3566,15 @@ public class FHIRPathEngine {
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "exp", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "exp", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcLn(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcLn(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "ln", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "ln", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3580,22 +3586,22 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ln", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ln", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcLog(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcLog(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "log", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "log", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
- List n1 = execute(context, focus, exp.getParameters().get(0), true);
+ List n1 = execute(context, focus, expr.getParameters().get(0), true);
if (n1.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "log", "0", "Multiple Values", "integer or decimal");
+ throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "log", "0", "Multiple Values", "integer or decimal");
}
Double e = Double.parseDouble(n1.get(0).primitiveValue());
Double d = Double.parseDouble(base.primitiveValue());
@@ -3605,7 +3611,7 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "log", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "log", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
@@ -3614,16 +3620,16 @@ public class FHIRPathEngine {
return Math.log(logNumber) / Math.log(base);
}
- private List funcPower(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcPower(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "power", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "power", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
- List n1 = execute(context, focus, exp.getParameters().get(0), true);
+ List n1 = execute(context, focus, expr.getParameters().get(0), true);
if (n1.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer or decimal");
+ throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer or decimal");
}
Double e = Double.parseDouble(n1.get(0).primitiveValue());
Double d = Double.parseDouble(base.primitiveValue());
@@ -3633,14 +3639,14 @@ public class FHIRPathEngine {
// just return nothing
}
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcTruncate(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcTruncate(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "truncate", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "truncate", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
@@ -3651,30 +3657,30 @@ public class FHIRPathEngine {
}
result.add(new IntegerType(s));
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
- private List funcRound(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcRound(ExecutionContext context, List focus, ExpressionNode expr) {
if (focus.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_FOCUS_PLURAL, "round", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "round", focus.size());
}
Base base = focus.get(0);
List result = new ArrayList();
if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
int i = 0;
- if (exp.getParameters().size() == 1) {
- List n1 = execute(context, focus, exp.getParameters().get(0), true);
+ if (expr.getParameters().size() == 1) {
+ List n1 = execute(context, focus, expr.getParameters().get(0), true);
if (n1.size() != 1) {
- throw makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer");
+ throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "power", "0", "Multiple Values", "integer");
}
i = Integer.parseInt(n1.get(0).primitiveValue());
}
BigDecimal d = new BigDecimal (base.primitiveValue());
result.add(new DecimalType(d.setScale(i, RoundingMode.HALF_UP)));
} else {
- makeException(I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "round", "(focus)", base.fhirType(), "integer or decimal");
+ makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "round", "(focus)", base.fhirType(), "integer or decimal");
}
return result;
}
@@ -3913,7 +3919,7 @@ public class FHIRPathEngine {
for (Base item : focus) {
pc.clear();
pc.add(item);
- Equality eq = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true));
+ Equality eq = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true), exp);
if (eq != Equality.True) {
all = false;
break;
@@ -4012,7 +4018,7 @@ public class FHIRPathEngine {
}
- private List funcReplace(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException, PathEngineException {
+ private List funcReplace(ExecutionContext context, List focus, ExpressionNode expr) throws FHIRException, PathEngineException {
List result = new ArrayList();
if (focus.size() == 1) {
@@ -4020,13 +4026,13 @@ public class FHIRPathEngine {
if (Utilities.noString(f)) {
result.add(new StringType(""));
} else {
- String t = convertToString(execute(context, focus, exp.getParameters().get(0), true));
- String r = convertToString(execute(context, focus, exp.getParameters().get(1), true));
+ String t = convertToString(execute(context, focus, expr.getParameters().get(0), true));
+ String r = convertToString(execute(context, focus, expr.getParameters().get(1), true));
String n = f.replace(t, r);
result.add(new StringType(n));
}
} else {
- throw makeException(I18nConstants.FHIRPATH_NO_COLLECTION, "replace", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_COLLECTION, "replace", focus.size());
}
return result;
}
@@ -4119,22 +4125,22 @@ public class FHIRPathEngine {
return result;
}
- private List funcToDateTime(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcToDateTime(ExecutionContext context, List focus, ExpressionNode expr) {
// List result = new ArrayList();
// result.add(new BooleanType(convertToBoolean(focus)));
// return result;
- throw makeException(I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toDateTime");
+ throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toDateTime");
}
- private List funcToTime(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcToTime(ExecutionContext context, List focus, ExpressionNode expr) {
// List result = new ArrayList();
// result.add(new BooleanType(convertToBoolean(focus)));
// return result;
- throw makeException(I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toTime");
+ throw makeException(expr, I18nConstants.FHIRPATH_NOT_IMPLEMENTED, "toTime");
}
- private List funcToDecimal(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcToDecimal(ExecutionContext context, List focus, ExpressionNode expr) {
String s = convertToString(focus);
List result = new ArrayList();
if (Utilities.isDecimal(s, true)) {
@@ -4152,7 +4158,7 @@ public class FHIRPathEngine {
private List funcIif(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException {
List n1 = execute(context, focus, exp.getParameters().get(0), true);
- Equality v = asBool(n1);
+ Equality v = asBool(n1, exp);
if (v == Equality.True) {
return execute(context, focus, exp.getParameters().get(1), true);
@@ -4227,28 +4233,28 @@ public class FHIRPathEngine {
}
- private List funcSingle(ExecutionContext context, List focus, ExpressionNode exp) throws PathEngineException {
+ private List funcSingle(ExecutionContext context, List focus, ExpressionNode expr) throws PathEngineException {
if (focus.size() == 1) {
return focus;
}
- throw makeException(I18nConstants.FHIRPATH_NO_COLLECTION, "single", focus.size());
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_COLLECTION, "single", focus.size());
}
- private List funcIs(ExecutionContext context, List focus, ExpressionNode exp) throws PathEngineException {
+ private List funcIs(ExecutionContext context, List focus, ExpressionNode expr) throws PathEngineException {
if (focus.size() == 0 || focus.size() > 1) {
return makeNull();
}
String ns = null;
String n = null;
- ExpressionNode texp = exp.getParameters().get(0);
+ ExpressionNode texp = expr.getParameters().get(0);
if (texp.getKind() != Kind.Name) {
- throw makeException(I18nConstants.FHIRPATH_PARAM_WRONG, texp.getKind(), "0", "is");
+ throw makeException(expr, I18nConstants.FHIRPATH_PARAM_WRONG, texp.getKind(), "0", "is");
}
if (texp.getInner() != null) {
if (texp.getInner().getKind() != Kind.Name) {
- throw makeException(I18nConstants.FHIRPATH_PARAM_WRONG, texp.getKind(), "1", "is");
+ throw makeException(expr, I18nConstants.FHIRPATH_PARAM_WRONG, texp.getKind(), "1", "is");
}
ns = texp.getName();
n = texp.getInner().getName();
@@ -4284,13 +4290,13 @@ public class FHIRPathEngine {
}
- private List funcAs(ExecutionContext context, List focus, ExpressionNode exp) {
+ private List funcAs(ExecutionContext context, List focus, ExpressionNode expr) {
List result = new ArrayList();
String tn;
- if (exp.getParameters().get(0).getInner() != null) {
- tn = exp.getParameters().get(0).getName()+"."+exp.getParameters().get(0).getInner().getName();
+ if (expr.getParameters().get(0).getInner() != null) {
+ tn = expr.getParameters().get(0).getName()+"."+expr.getParameters().get(0).getInner().getName();
} else {
- tn = "FHIR."+exp.getParameters().get(0).getName();
+ tn = "FHIR."+expr.getParameters().get(0).getName();
}
for (Base b : focus) {
if (tn.startsWith("System.")) {
@@ -4436,7 +4442,7 @@ public class FHIRPathEngine {
if (exp.getParameters().size() == 1) {
pc.clear();
pc.add(f);
- Equality v = asBool(execute(changeThis(context, f), pc, exp.getParameters().get(0), true));
+ Equality v = asBool(execute(changeThis(context, f), pc, exp.getParameters().get(0), true), exp);
if (v == Equality.True) {
empty = false;
}
@@ -4531,7 +4537,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v != Equality.False) {
all = false;
break;
@@ -4565,7 +4571,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v == Equality.False) {
any = true;
break;
@@ -4599,7 +4605,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v != Equality.True) {
all = false;
break;
@@ -4632,7 +4638,7 @@ public class FHIRPathEngine {
pc.clear();
pc.add(item);
List res = execute(context, pc, exp.getParameters().get(0), true);
- Equality v = asBool(res);
+ Equality v = asBool(res, exp);
if (v == Equality.True) {
any = true;
break;
@@ -4673,12 +4679,12 @@ public class FHIRPathEngine {
return focus;
}
- private List funcCheck(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException {
- List n1 = execute(context, focus, exp.getParameters().get(0), true);
+ private List funcCheck(ExecutionContext context, List focus, ExpressionNode expr) throws FHIRException {
+ List n1 = execute(context, focus, expr.getParameters().get(0), true);
if (!convertToBoolean(n1)) {
- List n2 = execute(context, focus, exp.getParameters().get(1), true);
+ List n2 = execute(context, focus, expr.getParameters().get(1), true);
String name = n2.get(0).primitiveValue();
- throw makeException(I18nConstants.FHIRPATH_CHECK_FAILED, name);
+ throw makeException(expr, I18nConstants.FHIRPATH_CHECK_FAILED, name);
}
return focus;
}
@@ -4940,15 +4946,15 @@ public class FHIRPathEngine {
return result;
}
- private List funcConformsTo(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException {
+ private List funcConformsTo(ExecutionContext context, List focus, ExpressionNode expr) throws FHIRException {
if (hostServices == null) {
- throw makeException(I18nConstants.FHIRPATH_HO_HOST_SERVICES, "conformsTo");
+ throw makeException(expr, I18nConstants.FHIRPATH_HO_HOST_SERVICES, "conformsTo");
}
List result = new ArrayList();
if (focus.size() != 1) {
result.add(new BooleanType(false).noExtensions());
} else {
- String url = convertToString(execute(context, focus, exp.getParameters().get(0), true));
+ String url = convertToString(execute(context, focus, expr.getParameters().get(0), true));
result.add(new BooleanType(hostServices.conformsToProfile(context.appInfo, focus.get(0), url)).noExtensions());
}
return result;
@@ -5111,7 +5117,7 @@ public class FHIRPathEngine {
for (Base item : focus) {
pc.clear();
pc.add(item);
- Equality v = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true));
+ Equality v = asBool(execute(changeThis(context, item), pc, exp.getParameters().get(0), true), exp);
if (v == Equality.True) {
result.add(item);
}
@@ -5148,7 +5154,7 @@ public class FHIRPathEngine {
private List funcNot(ExecutionContext context, List focus, ExpressionNode exp) throws PathEngineException {
List result = new ArrayList();
- Equality v = asBool(focus);
+ Equality v = asBool(focus, exp);
if (v != Equality.Null) {
result.add(new BooleanType(v != Equality.True));
}
@@ -5172,9 +5178,9 @@ public class FHIRPathEngine {
}
- private void getChildTypesByName(String type, String name, TypeDetails result) throws PathEngineException, DefinitionException {
+ private void getChildTypesByName(String type, String name, TypeDetails result, ExpressionNode expr) throws PathEngineException, DefinitionException {
if (Utilities.noString(type)) {
- throw makeException(I18nConstants.FHIRPATH_NO_TYPE, "", "getChildTypesByName");
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, "", "getChildTypesByName");
}
if (type.equals("http://hl7.org/fhir/StructureDefinition/xhtml")) {
return;
@@ -5197,24 +5203,24 @@ public class FHIRPathEngine {
String tail = "";
StructureDefinition sd = worker.fetchResource(StructureDefinition.class, url);
if (sd == null) {
- throw makeException(I18nConstants.FHIRPATH_NO_TYPE, url, "getChildTypesByName");
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, url, "getChildTypesByName");
}
List sdl = new ArrayList();
ElementDefinitionMatch m = null;
if (type.contains("#"))
- m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false);
+ m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr);
if (m != null && hasDataType(m.definition)) {
if (m.fixedType != null) {
StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, worker.getOverrideVersionNs()));
if (dt == null) {
- throw makeException(I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, worker.getOverrideVersionNs()), "getChildTypesByName");
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, worker.getOverrideVersionNs()), "getChildTypesByName");
}
sdl.add(dt);
} else
for (TypeRefComponent t : m.definition.getType()) {
StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(t.getCode(), worker.getOverrideVersionNs()));
if (dt == null) {
- throw makeException(I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(t.getCode(), worker.getOverrideVersionNs()), "getChildTypesByName");
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(t.getCode(), worker.getOverrideVersionNs()), "getChildTypesByName");
}
sdl.add(dt);
}
@@ -5243,11 +5249,11 @@ public class FHIRPathEngine {
if (t.getCode().equals("Resource")) {
for (String rn : worker.getResourceNames()) {
if (!result.hasType(worker, rn)) {
- getChildTypesByName(result.addType(rn), "**", result);
+ getChildTypesByName(result.addType(rn), "**", result, expr);
}
}
} else if (!result.hasType(worker, tn)) {
- getChildTypesByName(result.addType(tn), "**", result);
+ getChildTypesByName(result.addType(tn), "**", result, expr);
}
}
}
@@ -5271,7 +5277,7 @@ public class FHIRPathEngine {
} else {
path = sdi.getSnapshot().getElement().get(0).getPath()+tail+"."+name;
- ElementDefinitionMatch ed = getElementDefinition(sdi, path, isAllowPolymorphicNames());
+ ElementDefinitionMatch ed = getElementDefinition(sdi, path, isAllowPolymorphicNames(), expr);
if (ed != null) {
if (!Utilities.noString(ed.getFixedType()))
result.addType(ed.getFixedType());
@@ -5329,7 +5335,7 @@ public class FHIRPathEngine {
}
- private ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName) throws PathEngineException {
+ private ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName, ExpressionNode expr) throws PathEngineException {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().equals(path)) {
if (ed.hasContentReference()) {
@@ -5356,13 +5362,13 @@ public class FHIRPathEngine {
}
StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), worker.getOverrideVersionNs()));
if (nsd == null) {
- throw makeException(I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition");
+ throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition");
}
- return getElementDefinition(nsd, nsd.getId()+path.substring(ed.getPath().length()), allowTypedName);
+ return getElementDefinition(nsd, nsd.getId()+path.substring(ed.getPath().length()), allowTypedName, expr);
}
if (ed.hasContentReference() && path.startsWith(ed.getPath()+".")) {
ElementDefinitionMatch m = getElementDefinitionById(sd, ed.getContentReference());
- return getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName);
+ return getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
}
}
return null;
@@ -5430,7 +5436,7 @@ public class FHIRPathEngine {
if (element.hasSlicing()) {
ElementDefinition slice = pickMandatorySlice(sd, element);
if (slice == null) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_NAME_ALREADY_SLICED, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NAME_ALREADY_SLICED, element.getId());
}
element = slice;
}
@@ -5443,9 +5449,9 @@ public class FHIRPathEngine {
// if that's empty, get the children of the type
if (childDefinitions.isEmpty()) {
- sd = fetchStructureByType(element);
+ sd = fetchStructureByType(element, expr);
if (sd == null) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND, element.getType().get(0).getProfile(), element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND, element.getType().get(0).getProfile(), element.getId());
}
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
}
@@ -5459,20 +5465,20 @@ public class FHIRPathEngine {
} else if (expr.getKind() == Kind.Function) {
if ("resolve".equals(expr.getName())) {
if (!element.hasType()) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE, element.getId());
}
if (element.getType().size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_MULTIPLE_TYPES, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_MULTIPLE_TYPES, element.getId());
}
if (!element.getType().get(0).hasTarget()) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE, element.getId(), element.getType().get(0).getCode()+")");
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE, element.getId(), element.getType().get(0).getCode()+")");
}
if (element.getType().get(0).getTargetProfile().size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getId());
}
sd = worker.fetchResource(StructureDefinition.class, element.getType().get(0).getTargetProfile().get(0).getValue());
if (sd == null) {
- throw makeException(I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getType().get(0).getTargetProfile(), element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getType().get(0).getTargetProfile(), element.getId());
}
focus = sd.getSnapshot().getElementFirstRep();
} else if ("extension".equals(expr.getName())) {
@@ -5496,13 +5502,13 @@ public class FHIRPathEngine {
}
} else if ("ofType".equals(expr.getName())) {
if (!element.hasType()) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_NONE, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_NONE, element.getId());
}
if (element.getType().size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE, element.getId());
}
if (!element.getType().get(0).hasCode()) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_NO_CODE, element.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NO_CODE, element.getId());
}
String atn = element.getType().get(0).getCode();
String stn = expr.getParameters().get(0).getName();
@@ -5511,19 +5517,19 @@ public class FHIRPathEngine {
focus = element;
}
} else {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_NAME, expr.getName());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_NAME, expr.getName());
}
} else if (expr.getKind() == Kind.Group) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP);
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP);
} else if (expr.getKind() == Kind.Constant) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST);
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST);
}
if (focus == null) {
if (okToNotResolve) {
return null;
} else {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND, expr.toString());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND, expr.toString());
}
} else if (expr.getInner() == null) {
return focus;
@@ -5543,15 +5549,15 @@ public class FHIRPathEngine {
}
- private StructureDefinition fetchStructureByType(ElementDefinition ed) throws DefinitionException {
+ private StructureDefinition fetchStructureByType(ElementDefinition ed, ExpressionNode expr) throws DefinitionException {
if (ed.getType().size() == 0) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_NOTYPE, ed.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_NOTYPE, ed.getId());
}
if (ed.getType().size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_TYPES, ed.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_TYPES, ed.getId());
}
if (ed.getType().get(0).getProfile().size() > 1) {
- throw makeException(I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getId());
+ throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getId());
}
if (ed.getType().get(0).hasProfile()) {
return worker.fetchResource(StructureDefinition.class, ed.getType().get(0).getProfile().get(0).getValue());
@@ -5579,7 +5585,7 @@ public class FHIRPathEngine {
return path.substring(path.lastIndexOf(".") + 1);
}
- private Equality asBool(List items) throws PathEngineException {
+ private Equality asBool(List items, ExpressionNode expr) throws PathEngineException {
if (items.size() == 0) {
return Equality.Null;
} else if (items.size() == 1 && items.get(0).isBooleanPrimitive()) {
@@ -5587,7 +5593,7 @@ public class FHIRPathEngine {
} else if (items.size() == 1) {
return Equality.True;
} else {
- throw makeException(I18nConstants.FHIRPATH_UNABLE_BOOLEAN, convertToString(items));
+ throw makeException(expr, I18nConstants.FHIRPATH_UNABLE_BOOLEAN, convertToString(items));
}
}
diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java
index 322027805..22b3e3e21 100644
--- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java
+++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java
@@ -176,6 +176,7 @@ public class FHIRPathTests {
node = fp.parse(expression);
Assertions.assertTrue(fail != TestResultType.SYNTAX, String.format("Expected exception didn't occur parsing %s", expression));
} catch (Exception e) {
+ System.out.println("Parsing Error: "+e.getMessage());
Assertions.assertTrue(fail == TestResultType.SYNTAX, String.format("Unexpected exception parsing %s: " + e.getMessage(), expression));
}
@@ -193,6 +194,7 @@ public class FHIRPathTests {
}
Assertions.assertTrue(fail != TestResultType.SEMANTICS, String.format("Expected exception didn't occur checking %s", expression));
} catch (Exception e) {
+ System.out.println("Checking Error: "+e.getMessage());
Assertions.assertTrue(fail == TestResultType.SEMANTICS, String.format("Unexpected exception checking %s: " + e.getMessage(), expression));
node = null;
}
@@ -203,6 +205,7 @@ public class FHIRPathTests {
outcome = fp.evaluate(res, node);
Assertions.assertTrue(fail == TestResultType.OK, String.format("Expected exception didn't occur executing %s", expression));
} catch (Exception e) {
+ System.out.println("Execution Error: "+e.getMessage());
Assertions.assertTrue(fail == TestResultType.EXECUTION, String.format("Unexpected exception executing %s: " + e.getMessage(), expression));
node = null;
}
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/exceptions/PathEngineException.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/exceptions/PathEngineException.java
index 1eb33bdeb..b26a5ce16 100644
--- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/exceptions/PathEngineException.java
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/exceptions/PathEngineException.java
@@ -1,5 +1,8 @@
package org.hl7.fhir.exceptions;
+import org.hl7.fhir.utilities.SourceLocation;
+import org.hl7.fhir.utilities.Utilities;
+
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
@@ -33,20 +36,62 @@ package org.hl7.fhir.exceptions;
public class PathEngineException extends FHIRException {
+ private static final long serialVersionUID = 31969342112856390L;
+ private SourceLocation location;
+ private String expression;
+
public PathEngineException() {
super();
}
- public PathEngineException(String message, Throwable cause) {
- super(message, cause);
- }
+ public PathEngineException(String message, Throwable cause) {
+ super(message, cause);
+ }
- public PathEngineException(String message) {
- super(message);
- }
+ public PathEngineException(String message) {
+ super(message);
+ }
- public PathEngineException(Throwable cause) {
+ public PathEngineException(String message, SourceLocation location, String expression, Throwable cause) {
+ super(message+rep(location, expression), cause);
+ }
+
+ public PathEngineException(String message, SourceLocation location, String expression) {
+ super(message+rep(location, expression));
+ }
+
+ private static String rep(SourceLocation loc, String expr) {
+ if (loc != null) {
+ if (loc.getLine() == 1) {
+ return " (@char "+loc.getColumn()+")";
+ } else {
+ return " (@line "+loc.getLine()+" char "+loc.getColumn()+")";
+ }
+ } else if (Utilities.noString(expr)) { // can happen in some contexts...
+ return " (@~"+expr+")";
+ } else {
+ return "";
+ }
+ }
+
+ public PathEngineException(Throwable cause) {
super(cause);
}
+ public String getExpression() {
+ return expression;
+ }
+
+ public void setExpression(String expression) {
+ this.expression = expression;
+ }
+
+ public SourceLocation getLocation() {
+ return location;
+ }
+
+ public void setLocation(SourceLocation location) {
+ this.location = location;
+ }
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java
new file mode 100644
index 000000000..5ed864765
--- /dev/null
+++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SourceLocation.java
@@ -0,0 +1,27 @@
+package org.hl7.fhir.utilities;
+
+public class SourceLocation {
+ private int line;
+ private int column;
+ public SourceLocation(int line, int column) {
+ super();
+ this.line = line;
+ this.column = column;
+ }
+ public int getLine() {
+ return line;
+ }
+ public int getColumn() {
+ return column;
+ }
+ public void setLine(int line) {
+ this.line = line;
+ }
+ public void setColumn(int column) {
+ this.column = column;
+ }
+
+ public String toString() {
+ return Integer.toString(line)+", "+Integer.toString(column);
+ }
+}