fix bugs in FHIRPath engine, and work around wrong FHIRPath statements in the validator

This commit is contained in:
Grahame Grieve 2019-01-31 11:59:39 +11:00
parent 960e56705f
commit f2b619b08e
2 changed files with 41 additions and 18 deletions

View File

@ -1736,7 +1736,7 @@ public class FHIRPathEngine {
return makeBoolean(!res);
}
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary"};
private final static String[] FHIR_TYPES_STRING = new String[] {"string", "uri", "code", "oid", "id", "uuid", "sid", "markdown", "base64Binary", "canonical", "url"};
private List<Base> opLessThan(List<Base> left, List<Base> right) throws FHIRException {
if (left.size() == 0 || right.size() == 0)
@ -3200,7 +3200,7 @@ public class FHIRPathEngine {
private List<Base> funcIsDistinct(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
if (focus.size() < 1)
return new ArrayList<Base>();
return makeBoolean(true);
if (focus.size() == 1)
return makeBoolean(true);
@ -4239,22 +4239,29 @@ public class FHIRPathEngine {
private Equality asBool(Base item) {
if (item instanceof BooleanType)
return boolToTriState(((BooleanType) item).booleanValue());
else if (item instanceof IntegerType)
else if (item.isBooleanPrimitive()) {
if (Utilities.existsInList(item.primitiveValue(), "true"))
return Equality.True;
else if (Utilities.existsInList(item.primitiveValue(), "false"))
return Equality.False;
else
return Equality.Null;
} else if (item instanceof IntegerType || Utilities.existsInList(item.fhirType(), "integer", "positiveint", "unsignedInt"))
return asBoolFromInt(item.primitiveValue());
else if (item instanceof DecimalType)
else if (item instanceof DecimalType || Utilities.existsInList(item.fhirType(), "decimal"))
return asBoolFromDec(item.primitiveValue());
else if (Utilities.existsInList(item.fhirType(), FHIR_TYPES_STRING)) {
if (Utilities.existsInList(item.primitiveValue(), "true", "t", "yes", "y"))
return Equality.False;
else if (Utilities.existsInList(item.primitiveValue(), "false", "f", "no", "n"))
return Equality.True;
else if (Utilities.existsInList(item.primitiveValue(), "false", "f", "no", "n"))
return Equality.False;
else if (Utilities.isInteger(item.primitiveValue()))
return asBoolFromInt(item.primitiveValue());
else if (Utilities.isDecimal(item.primitiveValue()))
return asBoolFromDec(item.primitiveValue());
else
return Equality.Null;
} else
}
return Equality.Null;
}

View File

@ -2023,7 +2023,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
ElementDefinition ed = null;
ExpressionNode expr = fpe.parse(discriminator);
ExpressionNode expr = fpe.parse(fixExpr(discriminator));
long t2 = System.nanoTime();
ed = fpe.evaluateDefinition(expr, profile, element);
sdTime = sdTime + (System.nanoTime() - t2);
@ -2048,7 +2048,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (element == null)
throw new DefinitionException("Unable to resolve element "+id+" in profile "+p);
}
expr = fpe.parse(discriminator);
expr = fpe.parse(fixExpr(discriminator));
t2 = System.nanoTime();
ed = fpe.evaluateDefinition(expr, profile, element);
sdTime = sdTime + (System.nanoTime() - t2);
@ -2586,7 +2586,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
try {
n = fpe.parse(expression.toString());
n = fpe.parse(fixExpr(expression.toString()));
} catch (FHIRLexerException e) {
throw new FHIRException("Problem processing expression "+expression +" in profile " + profile.getUrl() + " path " + path + ": " + e.getMessage());
}
@ -3911,7 +3911,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (n == null) {
long t = System.nanoTime();
try {
n = fpe.parse(inv.getExpression());
n = fpe.parse(fixExpr(inv.getExpression()));
} catch (FHIRLexerException e) {
throw new FHIRException("Problem processing expression "+inv.getExpression() +" in profile " + profile.getUrl() + " path " + path + ": " + e.getMessage());
}
@ -3931,12 +3931,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
msg = ex.getMessage();
}
if (!ok) {
// GDG 18-feb 2018 - why do it again? just to waste cycles?
// try {
// ok = fpe.evaluateToBoolean(hostContext, resource, element, n);
// } catch (PathEngineException e) {
// throw new FHIRException("Problem processing expression "+inv.getExpression() +" in profile " + profile.getUrl() + " path " + path + ": " + e.getMessage());
// }
if (!Utilities.noString(msg))
msg = " ("+msg+")";
if (inv.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice") &&
@ -4311,7 +4305,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
ExpressionNode n = (ExpressionNode) inv.getUserData("validator.expression.cache");
if (n == null) {
n = fpe.parse(inv.getExpression());
n = fpe.parse(fixExpr(inv.getExpression()));
inv.setUserData("validator.expression.cache", n);
}
fpe.check(null, sd.getKind() == StructureDefinitionKind.RESOURCE ? sd.getType() : "DomainResource", ed.getPath(), n);
@ -4325,4 +4319,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
private String fixExpr(String expr) {
// this is a hack work around for past publication of wrong FHIRPath expressions
if ("(component.empty() and hasMember.empty()) implies (dataAbsentReason or value)".equals(expr))
return "(component.empty() and hasMember.empty()) implies (dataAbsentReason.exists() or value.exists())";
if ("isModifier implies isModifierReason.exists()".equals(expr))
return "(isModifier.exists() and isModifier) implies isModifierReason.exists()";
if ("(%resource.kind = 'logical' or element.first().path.startsWith(%resource.type)) and (element.tail().not() or element.tail().all(path.startsWith(%resource.differential.element.first().path.replaceMatches('\\\\..*','')&'.')))".equals(expr))
return "(%resource.kind = 'logical' or element.first().path.startsWith(%resource.type)) and (element.tail().empty() or element.tail().all(path.startsWith(%resource.differential.element.first().path.replaceMatches('\\\\..*','')&'.')))";
if ("differential.element.all(id) and differential.element.id.trace('ids').isDistinct()".equals(expr))
return "differential.element.all(id.exists()) and differential.element.id.trace('ids').isDistinct()";
if ("snapshot.element.all(id) and snapshot.element.id.trace('ids').isDistinct()".equals(expr))
return "snapshot.element.all(id.exists()) and snapshot.element.id.trace('ids').isDistinct()";
if ("".equals(expr))
return "";
if ("".equals(expr))
return "";
if ("".equals(expr))
return "";
return expr;
}
}