/*
* This software is subject to the terms of the Eclipse Public License v1.0
* Agreement, available at the following URL:
* http://www.eclipse.org/legal/epl-v10.html.
* You must accept the terms of that agreement to use this software.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package mondrian.olap.fun;
import mondrian.calc.Calc;
import mondrian.calc.ExpCompiler;
import mondrian.calc.impl.ConstantCalc;
import mondrian.calc.impl.GenericCalc;
import mondrian.mdx.ResolvedFunCall;
import mondrian.olap.*;
import java.util.ArrayList;
import java.util.List;
/**
* Definition of the matched <code>CASE</code> MDX operator.
*
* Syntax is:
* <blockquote><pre><code>Case <Expression>
* When <Expression> Then <Expression>
* [...]
* [Else <Expression>]
* End</code></blockquote>.
*
* @see CaseTestFunDef
* @author jhyde
* @since Mar 23, 2006
*/
class CaseMatchFunDef extends FunDefBase {
static final ResolverImpl Resolver = new ResolverImpl();
private CaseMatchFunDef(FunDef dummyFunDef) {
super(dummyFunDef);
}
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final Exp[] args = call.getArgs();
final List<Calc> calcList = new ArrayList<Calc>();
final Calc valueCalc =
compiler.compileScalar(args[0], true);
calcList.add(valueCalc);
final int matchCount = (args.length - 1) / 2;
final Calc[] matchCalcs = new Calc[matchCount];
final Calc[] exprCalcs = new Calc[matchCount];
for (int i = 0, j = 1; i < exprCalcs.length; i++) {
matchCalcs[i] = compiler.compileScalar(args[j++], true);
calcList.add(matchCalcs[i]);
exprCalcs[i] = compiler.compile(args[j++]);
calcList.add(exprCalcs[i]);
}
final Calc defaultCalc =
args.length % 2 == 0
? compiler.compile(args[args.length - 1])
: ConstantCalc.constantNull(call.getType());
calcList.add(defaultCalc);
final Calc[] calcs = calcList.toArray(new Calc[calcList.size()]);
return new GenericCalc(call) {
public Object evaluate(Evaluator evaluator) {
Object value = valueCalc.evaluate(evaluator);
for (int i = 0; i < matchCalcs.length; i++) {
Object match = matchCalcs[i].evaluate(evaluator);
if (match.equals(value)) {
return exprCalcs[i].evaluate(evaluator);
}
}
return defaultCalc.evaluate(evaluator);
}
public Calc[] getCalcs() {
return calcs;
}
};
}
private static class ResolverImpl extends ResolverBase {
private ResolverImpl() {
super(
"_CaseMatch",
"Case <Expression> When <Expression> Then <Expression> [...] [Else <Expression>] End",
"Evaluates various expressions, and returns the corresponding expression for the first which matches a particular value.",
Syntax.Case);
}
public FunDef resolve(
Exp[] args,
Validator validator,
List<Conversion> conversions)
{
if (args.length < 3) {
return null;
}
int valueType = args[0].getCategory();
int returnType = args[2].getCategory();
int j = 0;
int clauseCount = (args.length - 1) / 2;
int mismatchingArgs = 0;
if (!validator.canConvert(j, args[j++], valueType, conversions)) {
mismatchingArgs++;
}
for (int i = 0; i < clauseCount; i++) {
if (!validator.canConvert(j, args[j++], valueType, conversions))
{
mismatchingArgs++;
}
if (!validator.canConvert(
j, args[j++], returnType, conversions))
{
mismatchingArgs++;
}
}
if (j < args.length) {
if (!validator.canConvert(
j, args[j++], returnType, conversions))
{
mismatchingArgs++;
}
}
Util.assertTrue(j == args.length);
if (mismatchingArgs != 0) {
return null;
}
FunDef dummy = createDummyFunDef(this, returnType, args);
return new CaseMatchFunDef(dummy);
}
public boolean requiresExpression(int k) {
return true;
}
}
}
// End CaseMatchFunDef.java