Skip to content

Commit

Permalink
Multi source aggregate
Browse files Browse the repository at this point in the history
  • Loading branch information
JPercival committed Nov 2, 2023
1 parent 2ba9d37 commit 308b143
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.cqframework.cql.elm.visiting.ElmLibraryVisitor;
import org.hl7.elm.r1.AggregateClause;
import org.opencds.cqf.cql.engine.exception.CqlException;
import org.opencds.cqf.cql.engine.execution.State;
import org.opencds.cqf.cql.engine.execution.Variable;
import org.opencds.cqf.cql.engine.runtime.Tuple;

import java.util.List;
import java.util.Objects;
Expand All @@ -20,7 +22,7 @@

public class AggregateClauseEvaluator {

public static Object aggregate(AggregateClause elm, String alias, State state, ElmLibraryVisitor<Object, State> visitor, List<Object> elements) {
public static Object aggregate(AggregateClause elm, State state, ElmLibraryVisitor<Object, State> visitor, List<Object> elements) {
Objects.requireNonNull(elm, "elm can not be null");
Objects.requireNonNull(elements, "elements can not be null");
Objects.requireNonNull(state, "state can not be null");
Expand All @@ -36,15 +38,25 @@ public static Object aggregate(AggregateClause elm, String alias, State state, E

for(var e : elements) {
state.push(new Variable().withName(elm.getIdentifier()).withValue(aggregatedValue));
state.push(new Variable().withName(alias).withValue(e));
int pushes = 1;
if (!(e instanceof Tuple)) {
throw new CqlException("expected aggregation source to be a Tuple");
}
var tuple = (Tuple)e;
for (var p : tuple.getElements().entrySet()) {
state.push(new Variable().withName(p.getKey()).withValue(p.getValue()));
pushes++;
}

try {
aggregatedValue= visitor.visitExpression(elm.getExpression(), state);
}
finally {
state.pop();
state.pop();
while(pushes > 0) {
state.pop();
pushes--;
}
}

}

return aggregatedValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,22 @@ private static Object evaluateReturn(Query elm, State state, List<Variable> vari
: constructResult(state, variables, elements);
}

private static List<Object> evaluateAggregate(AggregateClause elm, String alias, State state, ElmLibraryVisitor<Object, State> visitor, List<Object> elements) {
return Collections.singletonList(AggregateClauseEvaluator.aggregate(elm, alias, state, visitor, elements));
private static List<Object> evaluateAggregate(AggregateClause elm, State state, ElmLibraryVisitor<Object, State> visitor, List<Object> elements) {
return Collections.singletonList(AggregateClauseEvaluator.aggregate(elm, state, visitor, elements));
}

private static Object constructTuple(State state, List<Variable> variables, List<Object> elements) {
LinkedHashMap<String, Object> elementMap = new LinkedHashMap<>();
for (int i = 0; i < variables.size(); i++) {
elementMap.put(variables.get(i).getName(), variables.get(i).getValue());
}

return new Tuple(state).withElements(elementMap);
}

private static Object constructResult(State state, List<Variable> variables, List<Object> elements) {
if (variables.size() > 1) {
LinkedHashMap<String, Object> elementMap = new LinkedHashMap<>();
for (int i = 0; i < variables.size(); i++) {
elementMap.put(variables.get(i).getName(), variables.get(i).getValue());
}

return new Tuple(state).withElements(elementMap);
return constructTuple(state, variables, elements);
}

return elements.get(0);
Expand Down Expand Up @@ -156,6 +160,9 @@ public Iterable<Object> getData() {

@SuppressWarnings("unchecked")
public static Object internalEvaluate(Query elm, State state, ElmLibraryVisitor<Object, State> visitor) {
if (elm.getAggregate() != null && elm.getReturn() != null) {
throw new CqlException("aggregate and return are mutually exclusive");
}

var sources = new ArrayList<Iterator<Object>>();
var variables = new ArrayList<Variable>();
Expand Down Expand Up @@ -203,7 +210,13 @@ public static Object internalEvaluate(Query elm, State state, ElmLibraryVisitor<
continue;
}

result.add(evaluateReturn(elm, state, variables, elements, visitor));
if (elm.getAggregate() != null) {
result.add(constructTuple(state, variables, elements));
}
else {
result.add(evaluateReturn(elm, state, variables, elements, visitor));
}

}
} finally {
while (pushCount > 0) {
Expand All @@ -212,18 +225,12 @@ public static Object internalEvaluate(Query elm, State state, ElmLibraryVisitor<
}
}

if (elm.getAggregate() != null && elm.getReturn() != null) {
throw new CqlException("aggregate and return are mutually exclusive");
}

if (elm.getReturn() != null && elm.getReturn().isDistinct()) {
result = DistinctEvaluator.distinct(result, state);
}

if (elm.getAggregate() != null) {
// TODO: JP - Hmm... this ain't right...
var alias = elm.getSource().get(0).getAlias();
result = evaluateAggregate(elm.getAggregate(), alias, state, visitor, result);
result = evaluateAggregate(elm.getAggregate(), state, visitor, result);
}

sortResult(elm, result, state, null, visitor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ define "B": {1, 2}
define "C": {1, 2}

define MegaMulti:
from "1" X, "2" Y, "3" Z
from "A" X, "B" Y, "C" Z
aggregate Agg starting 0: Agg + X + Y + Z // 36 -- (1+1+1)+(1+1+2)+(1+2+1)+(1+2+2)+(2+1+1)+(2+1+2)+(2+2+1)+(2+2+2)


Expand Down

0 comments on commit 308b143

Please sign in to comment.