/** * Chooses between two non null items based on the value of one of their argument * * @param first The first item on which make the choice * @param second The second item on which make the choice * @return The choosen item */ @Override protected T choose(T first, T second) { A firstArgument = argument.evaluate(first); if (firstArgument == null) return second; A secondArgument = argument.evaluate(second); if (secondArgument == null) return first; return chooseOnArgument(first, firstArgument, second, secondArgument); }
public Object execute(Evaluator evaluator, Argument[] arguments) { final Argument memberListExp = arguments[0]; final List memberList = (List) memberListExp.evaluate(evaluator); final Argument exp = arguments[1]; int nullCount = 0; int missCount = 0; for (int i = memberList.size() - 1; i >= 0; --i) { Member member = (Member) memberList.get(i); // Create an evaluator with the member as its context. Evaluator subEvaluator = evaluator.push(member); int missCountBefore = subEvaluator.getMissCount(); final Object o = exp.evaluateScalar(subEvaluator); int missCountAfter = subEvaluator.getMissCount(); if (Util.isNull(o)) { ++nullCount; continue; } if (missCountAfter > missCountBefore) { // There was a cache miss while evaluating the expression, so // the result is bogus. It would be a mistake to give up after // one cache miss, because then it would take us N // evaluate/fetch passes to move back through N members, which // is way too many. // // Carry on until we have seen as many misses as we have seen // null cells. The effect of this policy is that each pass // examines twice as many cells as the previous pass. Thus // we can move back through N members in log2(N) passes. ++missCount; if (missCount < 2 * nullCount + 1) { continue; } } if (o == RolapUtil.valueNotReadyException) { // Value is not in the cache yet, so we don't know whether // it will be empty. Carry on... continue; } if (o instanceof RuntimeException) { RuntimeException runtimeException = (RuntimeException) o; if (o == RolapUtil.valueNotReadyException) { // Value is not in the cache yet, so we don't know whether // it will be empty. Carry on... continue; } return runtimeException; } return member; } // Not found. Return the hierarchy's 'null member'. // It is possible that a MemberType has a Dimension but // no hierarchy, so we have to just get the type's Dimension's // default hierarchy and return it's null member. final Hierarchy hierarchy = memberListExp.getType().getHierarchy(); return (hierarchy == null) ? memberListExp.getType().getDimension().getHierarchies()[0].getNullMember() : hierarchy.getNullMember(); }
/** {@inheritDoc} */ public int compare(GroupItem<?> group1, GroupItem<?> group2) { return nullSafeCompare( argument.evaluate(group1.getGroupKey()), argument.evaluate(group2.getGroupKey())); }