FHIRPath fixes after last HAPI FHIR sync
This commit is contained in:
parent
3a1bd1c429
commit
c5a8beb3d1
|
@ -860,52 +860,75 @@ public abstract class BaseDateTimeType extends PrimitiveType<Date> {
|
||||||
return (myPrecision == TemporalPrecisionEnum.MINUTE || myPrecision == TemporalPrecisionEnum.SECOND || myPrecision == TemporalPrecisionEnum.MILLI);
|
return (myPrecision == TemporalPrecisionEnum.MINUTE || myPrecision == TemporalPrecisionEnum.SECOND || myPrecision == TemporalPrecisionEnum.MILLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method implements a datetime equality check using the rules as defined by FHIRPath.
|
* This method implements a datetime equality check using the rules as defined by FHIRPath.
|
||||||
*
|
*
|
||||||
* This method returns:
|
* This method returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>true if the given datetimes represent the exact same instant with the same precision (irrespective of the timezone)</li>
|
* <li>true if the given datetimes represent the exact same instant with the same precision (irrespective of the timezone)</li>
|
||||||
* <li>true if the given datetimes represent the exact same instant but one includes milliseconds of <code>.[0]+</code> while the other includes only SECONDS precision (irrespecitve of the timezone)</li>
|
* <li>true if the given datetimes represent the exact same instant but one includes milliseconds of <code>.[0]+</code> while the other includes only SECONDS precision (irrespecitve of the timezone)</li>
|
||||||
* <li>true if the given datetimes represent the exact same year/year-month/year-month-date (if both operands have the same precision)</li>
|
* <li>true if the given datetimes represent the exact same year/year-month/year-month-date (if both operands have the same precision)</li>
|
||||||
* <li>false if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could not represent the same instant in any timezone</li>
|
* <li>false if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could not represent the same instant in any timezone</li>
|
||||||
* <li>null if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could potentially represent the same instant in any timezone</li>
|
* <li>null if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could potentially represent the same instant in any timezone</li>
|
||||||
* <li>false if the given datetimes have the same precision but do not represent the same instant (irrespective of timezone)</li>
|
* <li>false if the given datetimes have the same precision but do not represent the same instant (irrespective of timezone)</li>
|
||||||
* <li>null otherwise (since these datetimes are not comparable)</li>
|
* <li>null otherwise (since these datetimes are not comparable)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) {
|
public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) {
|
||||||
|
|
||||||
if (hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) {
|
BaseDateTimeType me = this;
|
||||||
if (getPrecision() == theOther.getPrecision()) {
|
|
||||||
if (getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
|
||||||
boolean couldBeTheSameTime = couldBeTheSameTime(this, theOther) || couldBeTheSameTime(theOther, this);
|
|
||||||
if (!couldBeTheSameTime) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same precision
|
// Per FHIRPath rules, we compare equivalence at the lowest precision of the two values,
|
||||||
if (getPrecision() == theOther.getPrecision()) {
|
// so if we need to, we'll clone either side and reduce its precision
|
||||||
return getValue().getTime() == theOther.getValue().getTime();
|
int lowestPrecision = Math.min(me.getPrecision().ordinal(), theOther.getPrecision().ordinal());
|
||||||
}
|
TemporalPrecisionEnum lowestPrecisionEnum = TemporalPrecisionEnum.values()[lowestPrecision];
|
||||||
|
if (me.getPrecision() != lowestPrecisionEnum) {
|
||||||
|
me = new DateTimeType(me.getValueAsString());
|
||||||
|
me.setPrecision(lowestPrecisionEnum);
|
||||||
|
}
|
||||||
|
if (theOther.getPrecision() != lowestPrecisionEnum) {
|
||||||
|
theOther = new DateTimeType(theOther.getValueAsString());
|
||||||
|
theOther.setPrecision(lowestPrecisionEnum);
|
||||||
|
}
|
||||||
|
|
||||||
// Both represent 0 millis but the millis are optional
|
if (me.hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) {
|
||||||
if (((Integer)0).equals(getMillis())) {
|
if (me.getPrecision() == theOther.getPrecision()) {
|
||||||
if (((Integer)0).equals(theOther.getMillis())) {
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
||||||
if (getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
boolean couldBeTheSameTime = couldBeTheSameTime(me, theOther) || couldBeTheSameTime(theOther, me);
|
||||||
if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
if (!couldBeTheSameTime) {
|
||||||
return getValue().getTime() == theOther.getValue().getTime();
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
// Same precision
|
||||||
}
|
if (me.getPrecision() == theOther.getPrecision()) {
|
||||||
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
||||||
|
long leftTime = me.getValue().getTime();
|
||||||
|
long rightTime = theOther.getValue().getTime();
|
||||||
|
return leftTime == rightTime;
|
||||||
|
} else {
|
||||||
|
String leftTime = me.getValueAsString();
|
||||||
|
String rightTime = theOther.getValueAsString();
|
||||||
|
return leftTime.equals(rightTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both represent 0 millis but the millis are optional
|
||||||
|
if (((Integer)0).equals(me.getMillis())) {
|
||||||
|
if (((Integer)0).equals(theOther.getMillis())) {
|
||||||
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
||||||
|
if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
||||||
|
return me.getValue().getTime() == theOther.getValue().getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean couldBeTheSameTime(BaseDateTimeType theArg1, BaseDateTimeType theArg2) {
|
private boolean couldBeTheSameTime(BaseDateTimeType theArg1, BaseDateTimeType theArg2) {
|
||||||
boolean theCouldBeTheSameTime = false;
|
boolean theCouldBeTheSameTime = false;
|
||||||
|
|
|
@ -1436,13 +1436,15 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opAs(List<Base> left, List<Base> right) {
|
private List<Base> opAs(List<Base> left, List<Base> right) {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<>();
|
||||||
if (left.size() != 1 || right.size() != 1)
|
if (right.size() != 1)
|
||||||
return result;
|
return result;
|
||||||
else {
|
else {
|
||||||
String tn = convertToString(right);
|
String tn = convertToString(right);
|
||||||
if (tn.equals(left.get(0).fhirType()))
|
for (Base nextLeft : left) {
|
||||||
result.add(left.get(0));
|
if (tn.equals(nextLeft.fhirType()))
|
||||||
|
result.add(nextLeft);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3298,7 +3300,7 @@ public class FHIRPathEngine {
|
||||||
if (s.startsWith("#")) {
|
if (s.startsWith("#")) {
|
||||||
Property p = context.resource.getChildByName("contained");
|
Property p = context.resource.getChildByName("contained");
|
||||||
for (Base c : p.getValues()) {
|
for (Base c : p.getValues()) {
|
||||||
if (s.substring(1).equals(c.getIdBase())) {
|
if (chompHash(s).equals(chompHash(c.getIdBase()))) {
|
||||||
res = c;
|
res = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3314,7 +3316,18 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcExtension(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
/**
|
||||||
|
* Strips a leading hashmark (#) if present at the start of a string
|
||||||
|
*/
|
||||||
|
private String chompHash(String theId) {
|
||||||
|
String retVal = theId;
|
||||||
|
while (retVal.startsWith("#")) {
|
||||||
|
retVal = retVal.substring(1);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Base> funcExtension(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
String url = nl.get(0).primitiveValue();
|
String url = nl.get(0).primitiveValue();
|
||||||
|
|
|
@ -860,52 +860,75 @@ public abstract class BaseDateTimeType extends PrimitiveType<Date> {
|
||||||
return (myPrecision == TemporalPrecisionEnum.MINUTE || myPrecision == TemporalPrecisionEnum.SECOND || myPrecision == TemporalPrecisionEnum.MILLI);
|
return (myPrecision == TemporalPrecisionEnum.MINUTE || myPrecision == TemporalPrecisionEnum.SECOND || myPrecision == TemporalPrecisionEnum.MILLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method implements a datetime equality check using the rules as defined by FHIRPath.
|
* This method implements a datetime equality check using the rules as defined by FHIRPath.
|
||||||
*
|
*
|
||||||
* This method returns:
|
* This method returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>true if the given datetimes represent the exact same instant with the same precision (irrespective of the timezone)</li>
|
* <li>true if the given datetimes represent the exact same instant with the same precision (irrespective of the timezone)</li>
|
||||||
* <li>true if the given datetimes represent the exact same instant but one includes milliseconds of <code>.[0]+</code> while the other includes only SECONDS precision (irrespecitve of the timezone)</li>
|
* <li>true if the given datetimes represent the exact same instant but one includes milliseconds of <code>.[0]+</code> while the other includes only SECONDS precision (irrespecitve of the timezone)</li>
|
||||||
* <li>true if the given datetimes represent the exact same year/year-month/year-month-date (if both operands have the same precision)</li>
|
* <li>true if the given datetimes represent the exact same year/year-month/year-month-date (if both operands have the same precision)</li>
|
||||||
* <li>false if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could not represent the same instant in any timezone</li>
|
* <li>false if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could not represent the same instant in any timezone</li>
|
||||||
* <li>null if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could potentially represent the same instant in any timezone</li>
|
* <li>null if both datetimes have equal precision of MINUTE or greater, one has no timezone specified but the other does, and could potentially represent the same instant in any timezone</li>
|
||||||
* <li>false if the given datetimes have the same precision but do not represent the same instant (irrespective of timezone)</li>
|
* <li>false if the given datetimes have the same precision but do not represent the same instant (irrespective of timezone)</li>
|
||||||
* <li>null otherwise (since these datetimes are not comparable)</li>
|
* <li>null otherwise (since these datetimes are not comparable)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) {
|
public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) {
|
||||||
|
|
||||||
if (hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) {
|
BaseDateTimeType me = this;
|
||||||
if (getPrecision() == theOther.getPrecision()) {
|
|
||||||
if (getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
|
||||||
boolean couldBeTheSameTime = couldBeTheSameTime(this, theOther) || couldBeTheSameTime(theOther, this);
|
|
||||||
if (!couldBeTheSameTime) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same precision
|
// Per FHIRPath rules, we compare equivalence at the lowest precision of the two values,
|
||||||
if (getPrecision() == theOther.getPrecision()) {
|
// so if we need to, we'll clone either side and reduce its precision
|
||||||
return getValue().getTime() == theOther.getValue().getTime();
|
int lowestPrecision = Math.min(me.getPrecision().ordinal(), theOther.getPrecision().ordinal());
|
||||||
}
|
TemporalPrecisionEnum lowestPrecisionEnum = TemporalPrecisionEnum.values()[lowestPrecision];
|
||||||
|
if (me.getPrecision() != lowestPrecisionEnum) {
|
||||||
|
me = new DateTimeType(me.getValueAsString());
|
||||||
|
me.setPrecision(lowestPrecisionEnum);
|
||||||
|
}
|
||||||
|
if (theOther.getPrecision() != lowestPrecisionEnum) {
|
||||||
|
theOther = new DateTimeType(theOther.getValueAsString());
|
||||||
|
theOther.setPrecision(lowestPrecisionEnum);
|
||||||
|
}
|
||||||
|
|
||||||
// Both represent 0 millis but the millis are optional
|
if (me.hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) {
|
||||||
if (((Integer)0).equals(getMillis())) {
|
if (me.getPrecision() == theOther.getPrecision()) {
|
||||||
if (((Integer)0).equals(theOther.getMillis())) {
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
||||||
if (getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
boolean couldBeTheSameTime = couldBeTheSameTime(me, theOther) || couldBeTheSameTime(theOther, me);
|
||||||
if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
if (!couldBeTheSameTime) {
|
||||||
return getValue().getTime() == theOther.getValue().getTime();
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
// Same precision
|
||||||
}
|
if (me.getPrecision() == theOther.getPrecision()) {
|
||||||
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) {
|
||||||
|
long leftTime = me.getValue().getTime();
|
||||||
|
long rightTime = theOther.getValue().getTime();
|
||||||
|
return leftTime == rightTime;
|
||||||
|
} else {
|
||||||
|
String leftTime = me.getValueAsString();
|
||||||
|
String rightTime = theOther.getValueAsString();
|
||||||
|
return leftTime.equals(rightTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both represent 0 millis but the millis are optional
|
||||||
|
if (((Integer)0).equals(me.getMillis())) {
|
||||||
|
if (((Integer)0).equals(theOther.getMillis())) {
|
||||||
|
if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
||||||
|
if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) {
|
||||||
|
return me.getValue().getTime() == theOther.getValue().getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean couldBeTheSameTime(BaseDateTimeType theArg1, BaseDateTimeType theArg2) {
|
private boolean couldBeTheSameTime(BaseDateTimeType theArg1, BaseDateTimeType theArg2) {
|
||||||
boolean theCouldBeTheSameTime = false;
|
boolean theCouldBeTheSameTime = false;
|
||||||
|
|
|
@ -1436,13 +1436,15 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> opAs(List<Base> left, List<Base> right) {
|
private List<Base> opAs(List<Base> left, List<Base> right) {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<>();
|
||||||
if (left.size() != 1 || right.size() != 1)
|
if (right.size() != 1)
|
||||||
return result;
|
return result;
|
||||||
else {
|
else {
|
||||||
String tn = convertToString(right);
|
String tn = convertToString(right);
|
||||||
if (tn.equals(left.get(0).fhirType()))
|
for (Base nextLeft : left) {
|
||||||
result.add(left.get(0));
|
if (tn.equals(nextLeft.fhirType()))
|
||||||
|
result.add(nextLeft);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3298,7 +3300,7 @@ public class FHIRPathEngine {
|
||||||
if (s.startsWith("#")) {
|
if (s.startsWith("#")) {
|
||||||
Property p = context.resource.getChildByName("contained");
|
Property p = context.resource.getChildByName("contained");
|
||||||
for (Base c : p.getValues()) {
|
for (Base c : p.getValues()) {
|
||||||
if (s.substring(1).equals(c.getIdBase())) {
|
if (chompHash(s).equals(chompHash(c.getIdBase()))) {
|
||||||
res = c;
|
res = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3314,7 +3316,18 @@ public class FHIRPathEngine {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Base> funcExtension(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
/**
|
||||||
|
* Strips a leading hashmark (#) if present at the start of a string
|
||||||
|
*/
|
||||||
|
private String chompHash(String theId) {
|
||||||
|
String retVal = theId;
|
||||||
|
while (retVal.startsWith("#")) {
|
||||||
|
retVal = retVal.substring(1);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Base> funcExtension(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||||
List<Base> result = new ArrayList<Base>();
|
List<Base> result = new ArrayList<Base>();
|
||||||
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
|
||||||
String url = nl.get(0).primitiveValue();
|
String url = nl.get(0).primitiveValue();
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
<a href="Patient/f201">Roel</a>
|
<a href="Patient/f201">Roel</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>authored</b>: 18/06/2013 9:00:00 AM
|
<b>authored</b>: Jun. 17, 2013, 7:00:00 p.m.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>author</b>:
|
<b>author</b>:
|
||||||
|
|
Loading…
Reference in New Issue