Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically set units and precision in rules #391

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions aom/src/main/java/com/nedap/archie/rules/Operator.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void setOperands(List<Expression> operands) {
}

@JsonIgnore
protected Expression getFirstOperand() {
public Expression getFirstOperand() {
return operands.size() > 0 ? operands.get(0) : null;
}

Expand All @@ -44,7 +44,7 @@ protected void setFirstOperand(Expression firstOperand) {
}

@JsonIgnore
protected Expression getSecondOperand() {
public Expression getSecondOperand() {
return operands.size() > 1 ? operands.get(1) : null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -35,10 +43,98 @@ public static Map<String, Object> 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<String, Object> fixDvProportion(Object rmObject, Archetype archetype, String pathOfParent) {
try {
OperationalTemplate template = (OperationalTemplate) archetype;
Map<String, Object> result = new HashMap<>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two more todo's:

  • check if actually the magnitude is being set (see the pathOfParent.endsWith contruction elsewhere)
  • if units or precision already have a value, should they be set? You probably do not want to override a value set manually or with a different rule elsewhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check if actually the magnitude is being set (see the pathOfParent.endsWith contruction elsewhere)

I only see .../value in the pathOfParent when these quantities are being set by rule evaluation. Not sure how that would work then, or should I expect a .../value/magnitude path or something.


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<String, Object> 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<String, Object> fixForMagnitude(Object rmObject, OperationalTemplate template, String pathOfParent) {
Map<String, Object> 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<String> 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<Interval<Long>> cIntegerConstraint = cInteger.getConstraint();

if (cIntegerConstraint != null && cIntegerConstraint.size() == 1) {
Interval<Long> 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<String, Object> fixCodePhrase(Object rmObject, Archetype archetype, String pathOfParent) {
try {
//special case: if at-code has been set, we need to do more!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ private Collection<RMObjectWithPath> 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++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}


Expand Down