diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java
index 554dc8608..6203ef67c 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java
@@ -1662,6 +1662,9 @@ public class ProfileUtilities extends TranslatingUtilities {
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
b.append("](");
b.append(basePath);
+ if (!Utilities.noString(basePath) && !basePath.endsWith("/")) {
+ b.append("/");
+ }
i = i + 1;
} else {
b.append("](");
@@ -1740,8 +1743,11 @@ public class ProfileUtilities extends TranslatingUtilities {
url.startsWith("loinc.html") ||
url.startsWith("http.html") ||
url.startsWith("references") ||
+ url.startsWith("license.html") ||
url.startsWith("narrative.html") ||
url.startsWith("search.html") ||
+ url.startsWith("security.html") ||
+ url.startsWith("versions.html") ||
url.startsWith("patient-operation-match.html") ||
(url.startsWith("extension-") && url.contains(".html")) ||
url.startsWith("resource-definitions.html");
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java
index bd4f04a37..93f0ce092 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java
@@ -1314,5 +1314,52 @@ public class Element extends Base {
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;
+ }
+
}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base.java
index 3ffcab8bf..0aeba8345 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base.java
@@ -420,6 +420,8 @@ public abstract class Base implements Serializable, IBase, IElement {
return null;
}
+ public abstract Base copy();
+
public void copyValues(Base dst) {
}
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 0a3ae3746..e5af0adef 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
@@ -56,7 +56,7 @@ public class ExpressionNode {
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
// Local extensions to FHIRPath
- HtmlChecks1, HtmlChecks2, AliasAs, Alias;
+ HtmlChecks1, HtmlChecks2, AliasAs, Alias, Comparable;
public static Function fromCode(String name) {
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; // support change of care from R3
if (name.equals("htmlChecks2")) return Function.HtmlChecks2;
+ if (name.equals("comparable")) return Function.Comparable;
if (name.equals("encode")) return Function.Encode;
if (name.equals("decode")) return Function.Decode;
if (name.equals("escape")) return Function.Escape;
@@ -227,6 +228,7 @@ public class ExpressionNode {
case Join : return "join";
case HtmlChecks1 : return "htmlChecks";
case HtmlChecks2 : return "htmlChecks2";
+ case Comparable : return "comparable";
case OfType : return "ofType";
case Type : return "type";
case ToInteger : return "toInteger";
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Tuple.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Tuple.java
index ddffee042..0fff6567e 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Tuple.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Tuple.java
@@ -98,5 +98,12 @@ public class Tuple extends Base {
return getProperty(name.hashCode(), name, checkValid);
}
+ @Override
+ public Base copy() {
+ Tuple tuple = new Tuple();
+ copyValues(tuple);
+ return tuple;
+ }
+
}
\ No newline at end of file
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 f8f9f1d2a..238a1e87b 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
@@ -147,6 +147,11 @@ public class FHIRPathEngine {
public String primitiveValue() {
return value;
}
+
+ @Override
+ public Base copy() {
+ throw new Error("Not Implemented");
+ }
}
private class ClassTypeInfo extends Base {
@@ -205,6 +210,11 @@ public class FHIRPathEngine {
return instance.fhirType();
}
}
+
+ @Override
+ public Base copy() {
+ throw new Error("Not Implemented");
+ }
}
public static class TypedElementDefinition {
@@ -1403,6 +1413,7 @@ public class FHIRPathEngine {
case Join: return checkParamCount(lexer, location, exp, 1);
case HtmlChecks1: 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 ToDecimal: 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);
case HtmlChecks2 :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
+ case Comparable :
+ return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias :
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
@@ -3551,7 +3564,7 @@ public class FHIRPathEngine {
}
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());
}
}
@@ -3641,6 +3654,7 @@ public class FHIRPathEngine {
case Alias : return funcAlias(context, focus, exp);
case HtmlChecks1 : return funcHtmlChecks1(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 ToDecimal : return funcToDecimal(context, focus, exp);
case ToString : return funcToString(context, focus, exp);
@@ -3880,7 +3894,10 @@ public class FHIRPathEngine {
}
private List funcLowBoundary(ExecutionContext context, List 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());
}
int precision = 0;
@@ -3903,6 +3920,11 @@ public class FHIRPathEngine {
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
} else if (base.hasType("time")) {
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 {
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
}
@@ -3910,7 +3932,10 @@ public class FHIRPathEngine {
}
private List funcHighBoundary(ExecutionContext context, List 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());
}
int precision = 0;
@@ -3933,6 +3958,11 @@ public class FHIRPathEngine {
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
} else if (base.hasType("time")) {
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 {
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
}
@@ -4167,6 +4197,47 @@ public class FHIRPathEngine {
return false;
}
+ private List funcComparable(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException {
+ if (focus.size() != 1 || !(focus.get(0).fhirType().equals("Quantity"))) {
+ return makeBoolean(false);
+ }
+ List 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) {
if (node.getNodeType() == NodeType.Comment) {
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
index e4c93f55a..741203d27 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
@@ -106,6 +106,11 @@ public class GraphQLEngine implements IGraphQLEngine {
default: return super.getNamedProperty(_hash, _name, _checkValid);
}
}
+
+ @Override
+ public Base copy() {
+ throw new Error("Not Implemented");
+ }
}
public static class SearchWrapper extends Base {
@@ -195,6 +200,11 @@ public class GraphQLEngine implements IGraphQLEngine {
return null;
}
+ @Override
+ public Base copy() {
+ throw new Error("Not Implemented");
+ }
+
}
private IWorkerContext context;