diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/BaseDateTimeType.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/BaseDateTimeType.java index 9e35eb434..9ea16b1f7 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/BaseDateTimeType.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/BaseDateTimeType.java @@ -860,52 +860,75 @@ public abstract class BaseDateTimeType extends PrimitiveType { 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 returns: - * - */ - public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) { + /** + * This method implements a datetime equality check using the rules as defined by FHIRPath. + * + * This method returns: + * + */ + public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) { - if (hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) { - 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; - } + BaseDateTimeType me = this; - // Same precision - if (getPrecision() == theOther.getPrecision()) { - return getValue().getTime() == theOther.getValue().getTime(); - } + // Per FHIRPath rules, we compare equivalence at the lowest precision of the two values, + // so if we need to, we'll clone either side and reduce its precision + 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 (((Integer)0).equals(getMillis())) { - if (((Integer)0).equals(theOther.getMillis())) { - if (getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) { - if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) { - return getValue().getTime() == theOther.getValue().getTime(); - } - } - } - } + if (me.hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) { + if (me.getPrecision() == theOther.getPrecision()) { + if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) { + boolean couldBeTheSameTime = couldBeTheSameTime(me, theOther) || couldBeTheSameTime(theOther, me); + if (!couldBeTheSameTime) { + 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) { boolean theCouldBeTheSameTime = false; 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 ee9a2a848..4e29310fc 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 @@ -1436,13 +1436,15 @@ public class FHIRPathEngine { } private List opAs(List left, List right) { - List result = new ArrayList(); - if (left.size() != 1 || right.size() != 1) + List result = new ArrayList<>(); + if (right.size() != 1) return result; else { String tn = convertToString(right); - if (tn.equals(left.get(0).fhirType())) - result.add(left.get(0)); + for (Base nextLeft : left) { + if (tn.equals(nextLeft.fhirType())) + result.add(nextLeft); + } } return result; } @@ -3298,7 +3300,7 @@ public class FHIRPathEngine { if (s.startsWith("#")) { Property p = context.resource.getChildByName("contained"); for (Base c : p.getValues()) { - if (s.substring(1).equals(c.getIdBase())) { + if (chompHash(s).equals(chompHash(c.getIdBase()))) { res = c; break; } @@ -3314,7 +3316,18 @@ public class FHIRPathEngine { return result; } - private List funcExtension(ExecutionContext context, List 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 funcExtension(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException { List result = new ArrayList(); List nl = execute(context, focus, exp.getParameters().get(0), true); String url = nl.get(0).primitiveValue(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/BaseDateTimeType.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/BaseDateTimeType.java index 7d83c5ad1..8ff74fad0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/BaseDateTimeType.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/BaseDateTimeType.java @@ -860,52 +860,75 @@ public abstract class BaseDateTimeType extends PrimitiveType { 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 returns: - * - */ - public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) { + /** + * This method implements a datetime equality check using the rules as defined by FHIRPath. + * + * This method returns: + * + */ + public Boolean equalsUsingFhirPathRules(BaseDateTimeType theOther) { - if (hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) { - 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; - } + BaseDateTimeType me = this; - // Same precision - if (getPrecision() == theOther.getPrecision()) { - return getValue().getTime() == theOther.getValue().getTime(); - } + // Per FHIRPath rules, we compare equivalence at the lowest precision of the two values, + // so if we need to, we'll clone either side and reduce its precision + 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 (((Integer)0).equals(getMillis())) { - if (((Integer)0).equals(theOther.getMillis())) { - if (getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) { - if (theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.SECOND.ordinal()) { - return getValue().getTime() == theOther.getValue().getTime(); - } - } - } - } + if (me.hasTimezoneIfRequired() != theOther.hasTimezoneIfRequired()) { + if (me.getPrecision() == theOther.getPrecision()) { + if (me.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal() && theOther.getPrecision().ordinal() >= TemporalPrecisionEnum.MINUTE.ordinal()) { + boolean couldBeTheSameTime = couldBeTheSameTime(me, theOther) || couldBeTheSameTime(theOther, me); + if (!couldBeTheSameTime) { + 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) { boolean theCouldBeTheSameTime = false; 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 33bd3bf81..8f7fa237d 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 @@ -1436,13 +1436,15 @@ public class FHIRPathEngine { } private List opAs(List left, List right) { - List result = new ArrayList(); - if (left.size() != 1 || right.size() != 1) + List result = new ArrayList<>(); + if (right.size() != 1) return result; else { String tn = convertToString(right); - if (tn.equals(left.get(0).fhirType())) - result.add(left.get(0)); + for (Base nextLeft : left) { + if (tn.equals(nextLeft.fhirType())) + result.add(nextLeft); + } } return result; } @@ -3298,7 +3300,7 @@ public class FHIRPathEngine { if (s.startsWith("#")) { Property p = context.resource.getChildByName("contained"); for (Base c : p.getValues()) { - if (s.substring(1).equals(c.getIdBase())) { + if (chompHash(s).equals(chompHash(c.getIdBase()))) { res = c; break; } @@ -3314,7 +3316,18 @@ public class FHIRPathEngine { return result; } - private List funcExtension(ExecutionContext context, List 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 funcExtension(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException { List result = new ArrayList(); List nl = execute(context, focus, exp.getParameters().get(0), true); String url = nl.get(0).primitiveValue(); diff --git a/org.hl7.fhir.r5/src/main/resources/gen/gen.xml b/org.hl7.fhir.r5/src/main/resources/gen/gen.xml index d52962a14..8dc4230b9 100644 --- a/org.hl7.fhir.r5/src/main/resources/gen/gen.xml +++ b/org.hl7.fhir.r5/src/main/resources/gen/gen.xml @@ -111,7 +111,7 @@ Roel

- authored: 18/06/2013 9:00:00 AM + authored: Jun. 17, 2013, 7:00:00 p.m.

author: