diff --git a/aom/src/main/java/com/nedap/archie/rules/Operator.java b/aom/src/main/java/com/nedap/archie/rules/Operator.java index 6dc7aceef..046f76eef 100644 --- a/aom/src/main/java/com/nedap/archie/rules/Operator.java +++ b/aom/src/main/java/com/nedap/archie/rules/Operator.java @@ -35,7 +35,7 @@ public void setOperands(List operands) { } @JsonIgnore - protected Expression getFirstOperand() { + public Expression getFirstOperand() { return operands.size() > 0 ? operands.get(0) : null; } @@ -44,7 +44,7 @@ protected void setFirstOperand(Expression firstOperand) { } @JsonIgnore - protected Expression getSecondOperand() { + public Expression getSecondOperand() { return operands.size() > 1 ? operands.get(1) : null; } diff --git a/openehr-rm/src/main/java/com/nedap/archie/rminfo/UpdatedValueHandler.java b/openehr-rm/src/main/java/com/nedap/archie/rminfo/UpdatedValueHandler.java index 792e275d5..847901915 100644 --- a/openehr-rm/src/main/java/com/nedap/archie/rminfo/UpdatedValueHandler.java +++ b/openehr-rm/src/main/java/com/nedap/archie/rminfo/UpdatedValueHandler.java @@ -3,13 +3,17 @@ import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.nedap.archie.ArchieLanguageConfiguration; -import com.nedap.archie.aom.*; -import com.nedap.archie.aom.primitives.CTerminologyCode; +import com.nedap.archie.aom.Archetype; +import com.nedap.archie.aom.CAttribute; +import com.nedap.archie.aom.CAttributeTuple; +import com.nedap.archie.aom.CPrimitiveTuple; +import com.nedap.archie.aom.OperationalTemplate; +import com.nedap.archie.aom.primitives.CInteger; +import com.nedap.archie.aom.primitives.CString; import com.nedap.archie.aom.terminology.ArchetypeTerm; import com.nedap.archie.aom.terminology.ArchetypeTerminology; import com.nedap.archie.aom.utils.AOMUtils; import com.nedap.archie.base.Interval; -import com.nedap.archie.paths.PathSegment; import com.nedap.archie.query.APathQuery; import com.nedap.archie.query.RMObjectWithPath; import com.nedap.archie.query.RMPathQuery; @@ -18,15 +22,19 @@ import com.nedap.archie.rm.datatypes.CodePhrase; import com.nedap.archie.rm.datavalues.DvCodedText; import com.nedap.archie.rm.datavalues.quantity.DvOrdinal; +import com.nedap.archie.rm.datavalues.quantity.DvProportion; +import com.nedap.archie.rm.datavalues.quantity.DvQuantity; import com.nedap.archie.rm.support.identification.TerminologyId; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.xml.xpath.XPathExpressionException; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.xml.xpath.XPathExpressionException; + public class UpdatedValueHandler { private static final Logger logger = LoggerFactory.getLogger(UpdatedValueHandler.class); @@ -35,10 +43,98 @@ public static Map pathHasBeenUpdated(Object rmObject, Archetype if(parent instanceof CodePhrase) { return fixCodePhrase(rmObject, archetype, pathOfParent); } + if (parent instanceof DvQuantity) { + return fixDvQuantity(rmObject, archetype, pathOfParent); + } + if (parent instanceof DvProportion) { + return fixDvProportion(rmObject, archetype, pathOfParent); + } + return new HashMap<>(); + } + + private static Map fixDvProportion(Object rmObject, Archetype archetype, String pathOfParent) { + try { + OperationalTemplate template = (OperationalTemplate) archetype; + Map result = new HashMap<>(); + + RMPathQuery rmPathQuery = new RMPathQuery(pathOfParent); + + DvProportion proportion = rmPathQuery.find(ArchieRMInfoLookup.getInstance(), rmObject); + + // TODO Figure out how to not hardcode these + proportion.setDenominator(100.0); + result.put(pathOfParent + "/denominator", 100.0); + proportion.setType(2L); + result.put(pathOfParent + "/type", 2L); + proportion.setPrecision(1L); + result.put(pathOfParent + "/precision", 1L); + + return result; + } catch (Exception e) { + logger.warn("cannot fix DvProportion", e); + } return new HashMap<>(); } + private static Map fixDvQuantity(Object rmObject, Archetype archetype, String pathOfParent) { + try { + // TODO Check for magnitude? + // TODO Check if this fix actually needs to occur + return fixForMagnitude(rmObject, (OperationalTemplate) archetype, pathOfParent); + } catch (Exception e) { + logger.warn("cannot fix DvQuantity", e); + } + + return new HashMap<>(); + } + + private static Map fixForMagnitude(Object rmObject, OperationalTemplate template, String pathOfParent) { + Map result = new HashMap<>(); + + RMPathQuery rmPathQuery = new RMPathQuery(pathOfParent); + DvQuantity quantity = rmPathQuery.find(ArchieRMInfoLookup.getInstance(), rmObject); + + CAttribute units = template.getDefinition().itemAtPath(pathOfParent + "/units"); + CAttribute precision = template.getDefinition().itemAtPath(pathOfParent + "/precision"); + + if (units.getChildren().size() != 1) return result; // Only fix if there is 1 unit + + // Fix units + CString cString = (CString) units.getChildren().get(0); + List cStringConstraint = cString.getConstraint(); + if(cStringConstraint != null && cStringConstraint.size() == 1) { + String constraint = cStringConstraint.get(0); + if(!CString.isRegexConstraint(constraint)) { + quantity.setUnits(constraint); + result.put(pathOfParent + "/units", constraint); + } + } + + if (precision.getChildren().size() != 1) + return result; // Only fix if there is 1 precision + + // Fix precision + CInteger cInteger = (CInteger) precision.getChildren().get(0); + + List> cIntegerConstraint = cInteger.getConstraint(); + + if (cIntegerConstraint != null && cIntegerConstraint.size() == 1) { + Interval interval = cIntegerConstraint.get(0); + long value; + if (interval.isUpperUnbounded()) { + value = -1; + } else if (interval.isUpperIncluded() && interval.getUpper() != null) { + value = interval.getUpper(); + } else if (interval.getUpper() != null) { + value = interval.getUpper() -1 ; + } else throw new IllegalStateException("upper bound was not available"); + quantity.setPrecision(value); + result.put(pathOfParent + "/precision", value); + } + return result; + } + private static Map fixCodePhrase(Object rmObject, Archetype archetype, String pathOfParent) { try { //special case: if at-code has been set, we need to do more! diff --git a/path-queries/src/main/java/com/nedap/archie/query/RMPathQuery.java b/path-queries/src/main/java/com/nedap/archie/query/RMPathQuery.java index c15b14d66..93cc0fc14 100644 --- a/path-queries/src/main/java/com/nedap/archie/query/RMPathQuery.java +++ b/path-queries/src/main/java/com/nedap/archie/query/RMPathQuery.java @@ -245,7 +245,7 @@ private Collection findRMObjectsWithPathCollection(ModelInfoLo for(Object object:collection) { if(number == i) { //TODO: check for other constraints as well - return Lists.newArrayList(new RMObjectWithPath(object, path + buildPathConstraint(i-1, lookup.getArchetypeNodeIdFromRMObject(object)))); + return Lists.newArrayList(new RMObjectWithPath(object, path + buildPathConstraint(i, lookup.getArchetypeNodeIdFromRMObject(object)))); } i++; } diff --git a/tools/src/test/java/com/nedap/archie/adlparser/RMPathQueryTest.java b/tools/src/test/java/com/nedap/archie/adlparser/RMPathQueryTest.java index f13874401..741bee2e0 100644 --- a/tools/src/test/java/com/nedap/archie/adlparser/RMPathQueryTest.java +++ b/tools/src/test/java/com/nedap/archie/adlparser/RMPathQueryTest.java @@ -99,6 +99,14 @@ public void multipleItems() { for(RMObjectWithPath value:values) { assertEquals(value.getObject(), new RMPathQuery(value.getPath()).findList(modelInfoLookup, composition).get(0).getObject()); } + + // check that one result is returned when specifying an index, and with the correct path + values = new RMPathQuery("/context[id11]/other_context[id2]/items[id3,1]/items[id5]/value").findList(modelInfoLookup, composition); + assertEquals(1, values.size()); + assertEquals("/context/other_context[id2]/items[id3, 1]/items[id5, 2]/value", values.get(0).getPath()); + for(RMObjectWithPath value:values) { + assertEquals(value.getObject(), new RMPathQuery(value.getPath()).findList(modelInfoLookup, composition).get(0).getObject()); + } }