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;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractDoubleCalc;
014import mondrian.calc.impl.ValueCalc;
015import mondrian.mdx.ResolvedFunCall;
016import mondrian.olap.*;
017
018/**
019 * Definition of the <code>Median</code> MDX functions.
020 *
021 * @author jhyde
022 * @since Mar 23, 2006
023 */
024class MedianFunDef extends AbstractAggregateFunDef {
025    static final ReflectiveMultiResolver Resolver =
026        new ReflectiveMultiResolver(
027            "Median",
028            "Median(<Set>[, <Numeric Expression>])",
029            "Returns the median value of a numeric expression evaluated over a set.",
030            new String[]{"fnx", "fnxn"},
031            MedianFunDef.class);
032
033    public MedianFunDef(FunDef dummyFunDef) {
034        super(dummyFunDef);
035    }
036
037    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
038        final ListCalc listCalc =
039                compiler.compileList(call.getArg(0));
040        final Calc calc = call.getArgCount() > 1
041            ? compiler.compileScalar(call.getArg(1), true)
042            : new ValueCalc(call);
043        return new AbstractDoubleCalc(call, new Calc[] {listCalc, calc}) {
044            public double evaluateDouble(Evaluator evaluator) {
045                final int savepoint = evaluator.savepoint();
046                try {
047                    evaluator.setNonEmpty(false);
048                    TupleList list = evaluateCurrentList(listCalc, evaluator);
049                    final double percentile =
050                        percentile(
051                            evaluator, list, calc, 0.5);
052                    return percentile;
053                } finally {
054                    evaluator.restore(savepoint);
055                }
056            }
057
058            public boolean dependsOn(Hierarchy hierarchy) {
059                return anyDependsButFirst(getCalcs(), hierarchy);
060            }
061        };
062    }
063}
064
065// End MedianFunDef.java