001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2006-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap.fun.extra;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractDoubleCalc;
014import mondrian.calc.impl.ValueCalc;
015import mondrian.mdx.ResolvedFunCall;
016import mondrian.olap.*;
017import mondrian.olap.fun.*;
018
019/**
020 * Definition of the <code>FirstQ</code> and <code>ThirdQ</code> MDX extension
021 * functions.
022 *
023 * <p>These functions are not standard MDX.
024 *
025 * @author jhyde
026 * @since Mar 23, 2006
027 */
028public class NthQuartileFunDef extends AbstractAggregateFunDef {
029    private final int range;
030
031    public static final MultiResolver ThirdQResolver =
032        new ReflectiveMultiResolver(
033            "ThirdQ",
034            "ThirdQ(<Set>[, <Numeric Expression>])",
035            "Returns the 3rd quartile value of a numeric expression evaluated over a set.",
036            new String[]{"fnx", "fnxn"},
037        NthQuartileFunDef.class);
038
039    public static final MultiResolver FirstQResolver =
040        new ReflectiveMultiResolver(
041            "FirstQ",
042            "FirstQ(<Set>[, <Numeric Expression>])",
043            "Returns the 1st quartile value of a numeric expression evaluated over a set.",
044            new String[]{"fnx", "fnxn"},
045            NthQuartileFunDef.class);
046
047    public NthQuartileFunDef(FunDef dummyFunDef) {
048        super(dummyFunDef);
049        this.range = dummyFunDef.getName().equals("FirstQ") ? 1 : 3;
050    }
051
052    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
053        final ListCalc listCalc =
054            compiler.compileList(call.getArg(0));
055        final DoubleCalc doubleCalc =
056            call.getArgCount() > 1
057            ? compiler.compileDouble(call.getArg(1))
058            : new ValueCalc(call);
059        return new AbstractDoubleCalc(call, new Calc[] {listCalc, doubleCalc}) {
060            public double evaluateDouble(Evaluator evaluator) {
061                final int savepoint = evaluator.savepoint();
062                try {
063                    evaluator.setNonEmpty(false);
064                    TupleList members =
065                        evaluateCurrentList(listCalc, evaluator);
066                    return
067                        quartile(
068                            evaluator, members, doubleCalc, range);
069                } finally {
070                    evaluator.restore(savepoint);
071                }
072            }
073
074            public boolean dependsOn(Hierarchy hierarchy) {
075                return anyDependsButFirst(getCalcs(), hierarchy);
076            }
077        };
078    }
079}
080
081// End NthQuartileFunDef.java