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>Min</code> and <code>Max</code> MDX functions.
020 *
021 * @author jhyde
022 * @since Mar 23, 2006
023 */
024class MinMaxFunDef extends AbstractAggregateFunDef {
025    static final ReflectiveMultiResolver MinResolver =
026        new ReflectiveMultiResolver(
027            "Min",
028            "Min(<Set>[, <Numeric Expression>])",
029            "Returns the minimum value of a numeric expression evaluated over a set.",
030            new String[]{"fnx", "fnxn"},
031            MinMaxFunDef.class);
032
033    static final MultiResolver MaxResolver =
034        new ReflectiveMultiResolver(
035            "Max",
036            "Max(<Set>[, <Numeric Expression>])",
037            "Returns the maximum value of a numeric expression evaluated over a set.",
038            new String[]{"fnx", "fnxn"},
039            MinMaxFunDef.class);
040
041    private final boolean max;
042
043    public MinMaxFunDef(FunDef dummyFunDef) {
044        super(dummyFunDef);
045        this.max = dummyFunDef.getName().equals("Max");
046    }
047
048    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
049        final ListCalc listCalc =
050            compiler.compileList(call.getArg(0));
051        final Calc calc =
052            call.getArgCount() > 1
053            ? compiler.compileScalar(call.getArg(1), true)
054            : new ValueCalc(call);
055        return new AbstractDoubleCalc(call, new Calc[] {listCalc, calc}) {
056            public double evaluateDouble(Evaluator evaluator) {
057                TupleList memberList = evaluateCurrentList(listCalc, evaluator);
058                final int savepoint = evaluator.savepoint();
059                try {
060                    evaluator.setNonEmpty(false);
061                    final Double d = (Double) (max
062                        ? max(evaluator, memberList, calc)
063                            : min(evaluator, memberList, calc));
064                    return d;
065                } finally {
066                    evaluator.restore(savepoint);
067                }
068            }
069
070            public boolean dependsOn(Hierarchy hierarchy) {
071                return anyDependsButFirst(getCalcs(), hierarchy);
072            }
073        };
074    }
075}
076
077// End MinMaxFunDef.java