use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.
the class ToggleDrillStateFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
if (call.getArgCount() > 2) {
throw MondrianResource.instance().ToggleDrillStateRecursiveNotSupported.ex();
}
final ListCalc listCalc0 = compiler.compileList(call.getArg(0));
final ListCalc listCalc1 = compiler.compileList(call.getArg(1));
return new AbstractListCalc(call, new Calc[] { listCalc0, listCalc1 }) {
public TupleList evaluateList(Evaluator evaluator) {
final TupleList list0 = listCalc0.evaluateList(evaluator);
final TupleList list1 = listCalc1.evaluateList(evaluator);
return toggleDrillStateTuples(evaluator, list0, list1);
}
};
}
use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.
the class CachedExistsFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final ListCalc listCalc1 = compiler.compileList(call.getArg(0));
final TupleCalc tupleCalc1 = compiler.compileTuple(call.getArg(1));
final StringCalc stringCalc = compiler.compileString(call.getArg(2));
return new AbstractListCalc(call, new Calc[] { listCalc1, tupleCalc1, stringCalc }) {
public TupleList evaluateList(Evaluator evaluator) {
evaluator.getTiming().markStart(TIMING_NAME);
try {
Member[] subtotal = tupleCalc1.evaluateTuple(evaluator);
String namedSetName = stringCalc.evaluateString(evaluator);
Object cacheObj = evaluator.getQuery().getEvalCache(makeSetCacheKey(namedSetName, subtotal));
if (cacheObj != null) {
HashMap<String, TupleList> setCache = (HashMap<String, TupleList>) cacheObj;
TupleList tuples = setCache.get(makeSubtotalKey(subtotal));
if (tuples == null) {
tuples = TupleCollections.emptyList(listCalc1.getType().getArity());
}
return tuples;
}
// Build a mapping from subtotal tuple types to the input set's tuple types
List<Hierarchy> listHiers = getHierarchies(listCalc1.getType());
List<Hierarchy> subtotalHiers = getHierarchies(tupleCalc1.getType());
int[] subtotalToListIndex = new int[subtotalHiers.size()];
for (int i = 0; i < subtotalToListIndex.length; i++) {
Hierarchy subtotalHier = subtotalHiers.get(i);
boolean found = false;
for (int j = 0; j < listHiers.size(); j++) {
if (listHiers.get(j) == subtotalHier) {
subtotalToListIndex[i] = j;
found = true;
break;
}
}
if (!found) {
throw new IllegalArgumentException("Hierarchy in <Tuple> not present in <Set>");
}
}
// Build subtotal cache
HashMap<String, TupleList> setCache = new HashMap<String, TupleList>();
TupleList setToCache = listCalc1.evaluateList(evaluator);
for (List<Member> tuple : setToCache) {
String subtotalKey = makeSubtotalKey(subtotalToListIndex, tuple, subtotal);
TupleList tupleCache = setCache.get(subtotalKey);
if (tupleCache == null) {
tupleCache = TupleCollections.createList(listCalc1.getType().getArity());
setCache.put(subtotalKey, tupleCache);
}
tupleCache.add(tuple);
}
evaluator.getQuery().putEvalCache(makeSetCacheKey(namedSetName, subtotal), setCache);
TupleList tuples = setCache.get(makeSubtotalKey(subtotal));
if (tuples == null) {
tuples = TupleCollections.emptyList(listCalc1.getType().getArity());
}
return tuples;
} finally {
evaluator.getTiming().markEnd(TIMING_NAME);
}
}
};
}
use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.
the class SubsetFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final ListCalc listCalc = compiler.compileList(call.getArg(0));
final IntegerCalc startCalc = compiler.compileInteger(call.getArg(1));
final IntegerCalc countCalc = call.getArgCount() > 2 ? compiler.compileInteger(call.getArg(2)) : null;
return new AbstractListCalc(call, new Calc[] { listCalc, startCalc, countCalc }) {
public TupleList evaluateList(Evaluator evaluator) {
final int savepoint = evaluator.savepoint();
try {
evaluator.setNonEmpty(false);
final TupleList list = listCalc.evaluateList(evaluator);
final int start = startCalc.evaluateInteger(evaluator);
int end;
if (countCalc != null) {
final int count = countCalc.evaluateInteger(evaluator);
end = start + count;
} else {
end = list.size();
}
if (end > list.size()) {
end = list.size();
}
if (start >= end || start < 0) {
return TupleCollections.emptyList(list.getArity());
}
if (start == 0 && end == list.size()) {
return list;
}
assert 0 <= start;
assert start < end;
assert end <= list.size();
return list.subList(start, end);
} finally {
evaluator.restore(savepoint);
}
}
};
}
use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.
the class HierarchizeFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final ListCalc listCalc = compiler.compileList(call.getArg(0), true);
String order = getLiteralArg(call, 1, "PRE", prePost);
final boolean post = order.equals("POST");
return new AbstractListCalc(call, new Calc[] { listCalc }) {
public TupleList evaluateList(Evaluator evaluator) {
TupleList list = listCalc.evaluateList(evaluator);
return Sorter.hierarchizeTupleList(list, post);
}
};
}
use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.
the class IntersectFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final String literalArg = getLiteralArg(call, 2, "", ReservedWords);
final boolean all = literalArg.equalsIgnoreCase("ALL");
final int arity = call.getType().getArity();
final ListCalc listCalc1 = compiler.compileList(call.getArg(0));
final ListCalc listCalc2 = compiler.compileList(call.getArg(1));
return new AbstractListCalc(call, new Calc[] { listCalc1, listCalc2 }) {
public TupleList evaluateList(Evaluator evaluator) {
TupleList leftList = listCalc1.evaluateList(evaluator);
if (leftList.isEmpty()) {
return leftList;
}
final TupleList rightList = listCalc2.evaluateList(evaluator);
if (rightList.isEmpty()) {
return rightList;
}
// Set of members from the right side of the intersect.
// We use a RetrievableSet because distinct keys
// (regular members and visual totals members) compare
// identical using hashCode and equals, we want to retrieve
// the actual key, and java.util.Set only has containsKey.
RetrievableSet<List<Member>> rightSet = new RetrievableHashSet<List<Member>>(rightList.size() * 3 / 2);
for (List<Member> tuple : rightList) {
rightSet.add(tuple);
}
final TupleList result = TupleCollections.createList(arity, Math.min(leftList.size(), rightList.size()));
final Set<List<Member>> resultSet = all ? null : new HashSet<List<Member>>();
for (List<Member> leftTuple : leftList) {
List<Member> rightKey = rightSet.getKey(leftTuple);
if (rightKey == null) {
continue;
}
if (resultSet != null && !resultSet.add(leftTuple)) {
continue;
}
result.add(copyTupleWithVisualTotalsMembersOverriding(leftTuple, rightKey));
}
return result;
}
/**
* Constructs a tuple consisting of members from
* {@code leftTuple}, but overridden by any corresponding
* members from {@code rightKey} that happen to be visual totals
* members.
*
* <p>Returns the original tuple if there are no visual totals
* members on the RHS.
*
* @param leftTuple Original tuple
* @param rightKey Right tuple
* @return Copy of original tuple, with any VisualTotalMembers
* from right tuple overriding
*/
private List<Member> copyTupleWithVisualTotalsMembersOverriding(List<Member> leftTuple, List<Member> rightKey) {
List<Member> tuple = leftTuple;
for (int i = 0; i < rightKey.size(); i++) {
Member member = rightKey.get(i);
if (!(tuple.get(i) instanceof VisualTotalsFunDef.VisualTotalMember) && member instanceof VisualTotalsFunDef.VisualTotalMember) {
if (tuple == leftTuple) {
// clone on first VisualTotalMember -- to avoid
// alloc/copy in the common case where there are
// no VisualTotalMembers
tuple = new ArrayList<Member>(leftTuple);
}
tuple.set(i, member);
}
}
return tuple;
}
};
}
Aggregations