Merge pull request #1111 from hapifhir/gg-202302-comparable
FHIR-34417: implementations for comparable(), highBoundary(), lowBoun…
This commit is contained in:
commit
63e1827a2b
|
@ -1662,6 +1662,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
|
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
|
||||||
b.append("](");
|
b.append("](");
|
||||||
b.append(basePath);
|
b.append(basePath);
|
||||||
|
if (!Utilities.noString(basePath) && !basePath.endsWith("/")) {
|
||||||
|
b.append("/");
|
||||||
|
}
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
} else {
|
} else {
|
||||||
b.append("](");
|
b.append("](");
|
||||||
|
@ -1740,8 +1743,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
url.startsWith("loinc.html") ||
|
url.startsWith("loinc.html") ||
|
||||||
url.startsWith("http.html") ||
|
url.startsWith("http.html") ||
|
||||||
url.startsWith("references") ||
|
url.startsWith("references") ||
|
||||||
|
url.startsWith("license.html") ||
|
||||||
url.startsWith("narrative.html") ||
|
url.startsWith("narrative.html") ||
|
||||||
url.startsWith("search.html") ||
|
url.startsWith("search.html") ||
|
||||||
|
url.startsWith("security.html") ||
|
||||||
|
url.startsWith("versions.html") ||
|
||||||
url.startsWith("patient-operation-match.html") ||
|
url.startsWith("patient-operation-match.html") ||
|
||||||
(url.startsWith("extension-") && url.contains(".html")) ||
|
(url.startsWith("extension-") && url.contains(".html")) ||
|
||||||
url.startsWith("resource-definitions.html");
|
url.startsWith("resource-definitions.html");
|
||||||
|
|
|
@ -1315,4 +1315,51 @@ public class Element extends Base {
|
||||||
throw new Error("Unrecognised name "+name+" on "+this.name);
|
throw new Error("Unrecognised name "+name+" on "+this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
Element element = new Element(this);
|
||||||
|
this.copyValues(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyValues(Base dst) {
|
||||||
|
super.copyValues(dst);
|
||||||
|
|
||||||
|
Element dest = (Element) dst;
|
||||||
|
if (comments != null) {
|
||||||
|
dest.comments = new ArrayList<>();
|
||||||
|
dest.comments.addAll(comments);
|
||||||
|
} else {
|
||||||
|
dest.comments = null;
|
||||||
|
}
|
||||||
|
dest.value = value;
|
||||||
|
if (children != null) {
|
||||||
|
dest.children = new ArrayList<>();
|
||||||
|
dest.children.addAll(children);
|
||||||
|
} else {
|
||||||
|
dest.children = null;
|
||||||
|
}
|
||||||
|
dest.line = line;
|
||||||
|
dest.col = col;
|
||||||
|
dest.xhtml = xhtml;
|
||||||
|
dest.explicitType = explicitType;
|
||||||
|
dest.hasParentForValidator = false;
|
||||||
|
dest.path = path;
|
||||||
|
dest.messages = null;
|
||||||
|
dest.prohibited = prohibited;
|
||||||
|
dest.required = required;
|
||||||
|
dest.childMap = null;
|
||||||
|
dest.descendentCount = descendentCount;
|
||||||
|
dest.instanceId = instanceId;
|
||||||
|
dest.isNull = isNull;
|
||||||
|
dest.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Base setProperty(String name, Base value) throws FHIRException {
|
||||||
|
setChildValue(name, value.primitiveValue());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -420,6 +420,8 @@ public abstract class Base implements Serializable, IBase, IElement {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract Base copy();
|
||||||
|
|
||||||
public void copyValues(Base dst) {
|
public void copyValues(Base dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class ExpressionNode {
|
||||||
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
|
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
|
||||||
|
|
||||||
// Local extensions to FHIRPath
|
// Local extensions to FHIRPath
|
||||||
HtmlChecks1, HtmlChecks2, AliasAs, Alias;
|
HtmlChecks1, HtmlChecks2, AliasAs, Alias, Comparable;
|
||||||
|
|
||||||
public static Function fromCode(String name) {
|
public static Function fromCode(String name) {
|
||||||
if (name.equals("empty")) return Function.Empty;
|
if (name.equals("empty")) return Function.Empty;
|
||||||
|
@ -118,6 +118,7 @@ public class ExpressionNode {
|
||||||
if (name.equals("htmlChecks")) return Function.HtmlChecks1;
|
if (name.equals("htmlChecks")) return Function.HtmlChecks1;
|
||||||
if (name.equals("htmlchecks")) return Function.HtmlChecks1; // support change of care from R3
|
if (name.equals("htmlchecks")) return Function.HtmlChecks1; // support change of care from R3
|
||||||
if (name.equals("htmlChecks2")) return Function.HtmlChecks2;
|
if (name.equals("htmlChecks2")) return Function.HtmlChecks2;
|
||||||
|
if (name.equals("comparable")) return Function.Comparable;
|
||||||
if (name.equals("encode")) return Function.Encode;
|
if (name.equals("encode")) return Function.Encode;
|
||||||
if (name.equals("decode")) return Function.Decode;
|
if (name.equals("decode")) return Function.Decode;
|
||||||
if (name.equals("escape")) return Function.Escape;
|
if (name.equals("escape")) return Function.Escape;
|
||||||
|
@ -227,6 +228,7 @@ public class ExpressionNode {
|
||||||
case Join : return "join";
|
case Join : return "join";
|
||||||
case HtmlChecks1 : return "htmlChecks";
|
case HtmlChecks1 : return "htmlChecks";
|
||||||
case HtmlChecks2 : return "htmlChecks2";
|
case HtmlChecks2 : return "htmlChecks2";
|
||||||
|
case Comparable : return "comparable";
|
||||||
case OfType : return "ofType";
|
case OfType : return "ofType";
|
||||||
case Type : return "type";
|
case Type : return "type";
|
||||||
case ToInteger : return "toInteger";
|
case ToInteger : return "toInteger";
|
||||||
|
|
|
@ -98,5 +98,12 @@ public class Tuple extends Base {
|
||||||
return getProperty(name.hashCode(), name, checkValid);
|
return getProperty(name.hashCode(), name, checkValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
Tuple tuple = new Tuple();
|
||||||
|
copyValues(tuple);
|
||||||
|
return tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -147,6 +147,11 @@ public class FHIRPathEngine {
|
||||||
public String primitiveValue() {
|
public String primitiveValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("Not Implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ClassTypeInfo extends Base {
|
private class ClassTypeInfo extends Base {
|
||||||
|
@ -205,6 +210,11 @@ public class FHIRPathEngine {
|
||||||
return instance.fhirType();
|
return instance.fhirType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("Not Implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypedElementDefinition {
|
public static class TypedElementDefinition {
|
||||||
|
@ -1403,6 +1413,7 @@ public class FHIRPathEngine {
|
||||||
case Join: return checkParamCount(lexer, location, exp, 1);
|
case Join: return checkParamCount(lexer, location, exp, 1);
|
||||||
case HtmlChecks1: return checkParamCount(lexer, location, exp, 0);
|
case HtmlChecks1: return checkParamCount(lexer, location, exp, 0);
|
||||||
case HtmlChecks2: return checkParamCount(lexer, location, exp, 0);
|
case HtmlChecks2: return checkParamCount(lexer, location, exp, 0);
|
||||||
|
case Comparable: return checkParamCount(lexer, location, exp, 1);
|
||||||
case ToInteger: return checkParamCount(lexer, location, exp, 0);
|
case ToInteger: return checkParamCount(lexer, location, exp, 0);
|
||||||
case ToDecimal: return checkParamCount(lexer, location, exp, 0);
|
case ToDecimal: return checkParamCount(lexer, location, exp, 0);
|
||||||
case ToString: return checkParamCount(lexer, location, exp, 0);
|
case ToString: return checkParamCount(lexer, location, exp, 0);
|
||||||
|
@ -3335,6 +3346,8 @@ public class FHIRPathEngine {
|
||||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
|
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
|
||||||
case HtmlChecks2 :
|
case HtmlChecks2 :
|
||||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
|
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
|
||||||
|
case Comparable :
|
||||||
|
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
|
||||||
case Alias :
|
case Alias :
|
||||||
checkParamTypes(exp, 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);
|
return anything(CollectionStatus.SINGLETON);
|
||||||
|
@ -3551,7 +3564,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
|
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
|
||||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time")) {
|
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time") && !focus.hasType("Quantity")) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_CONTINUOUS_ONLY, name, focus.describe());
|
throw makeException(expr, I18nConstants.FHIRPATH_CONTINUOUS_ONLY, name, focus.describe());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3641,6 +3654,7 @@ public class FHIRPathEngine {
|
||||||
case Alias : return funcAlias(context, focus, exp);
|
case Alias : return funcAlias(context, focus, exp);
|
||||||
case HtmlChecks1 : return funcHtmlChecks1(context, focus, exp);
|
case HtmlChecks1 : return funcHtmlChecks1(context, focus, exp);
|
||||||
case HtmlChecks2 : return funcHtmlChecks2(context, focus, exp);
|
case HtmlChecks2 : return funcHtmlChecks2(context, focus, exp);
|
||||||
|
case Comparable : return funcComparable(context, focus, exp);
|
||||||
case ToInteger : return funcToInteger(context, focus, exp);
|
case ToInteger : return funcToInteger(context, focus, exp);
|
||||||
case ToDecimal : return funcToDecimal(context, focus, exp);
|
case ToDecimal : return funcToDecimal(context, focus, exp);
|
||||||
case ToString : return funcToString(context, focus, exp);
|
case ToString : return funcToString(context, focus, exp);
|
||||||
|
@ -3880,7 +3894,10 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcLowBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcLowBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
if (focus.size() != 1) {
|
if (focus.size() == 0) {
|
||||||
|
return makeNull();
|
||||||
|
}
|
||||||
|
if (focus.size() > 1) {
|
||||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "lowBoundary", focus.size());
|
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "lowBoundary", focus.size());
|
||||||
}
|
}
|
||||||
int precision = 0;
|
int precision = 0;
|
||||||
|
@ -3903,6 +3920,11 @@ public class FHIRPathEngine {
|
||||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||||
} else if (base.hasType("time")) {
|
} else if (base.hasType("time")) {
|
||||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||||
|
} else if (base.hasType("Quantity")) {
|
||||||
|
String value = getNamedValue(base, "value");
|
||||||
|
Base v = base.copy();
|
||||||
|
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||||
|
result.add(v);
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||||
}
|
}
|
||||||
|
@ -3910,7 +3932,10 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcHighBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
private List<Base> funcHighBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||||
if (focus.size() != 1) {
|
if (focus.size() == 0) {
|
||||||
|
return makeNull();
|
||||||
|
}
|
||||||
|
if (focus.size() > 1) {
|
||||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||||
}
|
}
|
||||||
int precision = 0;
|
int precision = 0;
|
||||||
|
@ -3933,6 +3958,11 @@ public class FHIRPathEngine {
|
||||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||||
} else if (base.hasType("time")) {
|
} else if (base.hasType("time")) {
|
||||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||||
|
} else if (base.hasType("Quantity")) {
|
||||||
|
String value = getNamedValue(base, "value");
|
||||||
|
Base v = base.copy();
|
||||||
|
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||||
|
result.add(v);
|
||||||
} else {
|
} else {
|
||||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||||
}
|
}
|
||||||
|
@ -4167,6 +4197,47 @@ public class FHIRPathEngine {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Base> funcComparable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
|
if (focus.size() != 1 || !(focus.get(0).fhirType().equals("Quantity"))) {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
|
if (nl.size() != 1 || !(nl.get(0).fhirType().equals("Quantity"))) {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
String s1 = getNamedValue(focus.get(0), "system");
|
||||||
|
String u1 = getNamedValue(focus.get(0), "code");
|
||||||
|
String s2 = getNamedValue(nl.get(0), "system");
|
||||||
|
String u2 = getNamedValue(nl.get(0), "code");
|
||||||
|
|
||||||
|
if (s1 == null || s2 == null || !s1.equals(s2)) {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
if (u1 == null || u2 == null) {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
if (u1.equals(u2)) {
|
||||||
|
return makeBoolean(true);
|
||||||
|
}
|
||||||
|
if (s1.equals("http://unitsofmeasure.org") && worker.getUcumService() != null) {
|
||||||
|
try {
|
||||||
|
return makeBoolean(worker.getUcumService().isComparable(u1, u2));
|
||||||
|
} catch (UcumException e) {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return makeBoolean(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getNamedValue(Base base, String name) {
|
||||||
|
Property p = base.getChildByName(name);
|
||||||
|
if (p.hasValues() && p.getValues().size() == 1) {
|
||||||
|
return p.getValues().get(0).primitiveValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkHtmlNames(XhtmlNode node) {
|
private boolean checkHtmlNames(XhtmlNode node) {
|
||||||
if (node.getNodeType() == NodeType.Comment) {
|
if (node.getNodeType() == NodeType.Comment) {
|
||||||
|
|
|
@ -106,6 +106,11 @@ public class GraphQLEngine implements IGraphQLEngine {
|
||||||
default: return super.getNamedProperty(_hash, _name, _checkValid);
|
default: return super.getNamedProperty(_hash, _name, _checkValid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("Not Implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SearchWrapper extends Base {
|
public static class SearchWrapper extends Base {
|
||||||
|
@ -195,6 +200,11 @@ public class GraphQLEngine implements IGraphQLEngine {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Base copy() {
|
||||||
|
throw new Error("Not Implemented");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWorkerContext context;
|
private IWorkerContext context;
|
||||||
|
|
Loading…
Reference in New Issue