001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/SumFunDef.java#9 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2006-2007 Julian Hyde
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.olap.fun;
011    
012    import mondrian.olap.*;
013    import mondrian.calc.*;
014    import mondrian.calc.impl.ValueCalc;
015    import mondrian.calc.impl.AbstractDoubleCalc;
016    import mondrian.mdx.ResolvedFunCall;
017    
018    import java.util.List;
019    import java.util.Collections;
020    
021    /**
022     * Definition of the <code>Sum</code> MDX function.
023     *
024     * @author jhyde
025     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/SumFunDef.java#9 $
026     * @since Mar 23, 2006
027     */
028    class SumFunDef extends AbstractAggregateFunDef {
029        static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
030                "Sum",
031                "Sum(<Set>[, <Numeric Expression>])",
032                "Returns the sum of a numeric expression evaluated over a set.",
033                new String[]{"fnx", "fnxn"},
034                SumFunDef.class);
035    
036        public SumFunDef(FunDef dummyFunDef) {
037            super(dummyFunDef);
038        }
039    
040        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
041            // What is the desired type to use to get the underlying values
042            for (ResultStyle r : compiler.getAcceptableResultStyles()) {
043                switch (r) {
044                case ITERABLE:
045                case ANY:
046                    // Consumer wants ITERABLE or ANY to be used
047                    //return compileCallIterable(call, compiler);
048                    return compileCall(call, compiler, ResultStyle.ITERABLE);
049                case MUTABLE_LIST:
050                    // Consumer wants MUTABLE_LIST
051                    return compileCall(call, compiler, ResultStyle.MUTABLE_LIST);
052                case LIST:
053                    // Consumer wants LIST to be used
054                    //return compileCallList(call, compiler);
055                    return compileCall(call, compiler, ResultStyle.LIST);
056                }
057            }
058            throw ResultStyleException.generate(
059                ResultStyle.ITERABLE_LIST_MUTABLELIST_ANY,
060                compiler.getAcceptableResultStyles());
061        }
062    
063        protected Calc compileCall(
064            final ResolvedFunCall call,
065            ExpCompiler compiler,
066            ResultStyle resultStyle)
067        {
068            final Calc ncalc = compiler.compileAs(
069                call.getArg(0),
070                null,
071                Collections.singletonList(resultStyle));
072            final Calc calc = call.getArgCount() > 1 ?
073                compiler.compileScalar(call.getArg(1), true) :
074                new ValueCalc(call);
075            // we may have asked for one sort of Calc, but here's what we got.
076            if (ncalc instanceof ListCalc) {
077                return genListCalc(call, ncalc, calc);
078            } else {
079                return genIterCalc(call, ncalc, calc);
080            }
081        }
082        protected Calc genIterCalc(final ResolvedFunCall call,
083                final Calc ncalc, final Calc calc) {
084            return new AbstractDoubleCalc(call, new Calc[] {ncalc, calc}) {
085                public double evaluateDouble(Evaluator evaluator) {
086                    IterCalc iterCalc = (IterCalc) ncalc;
087                    Iterable iterable =
088                        evaluateCurrentIterable(iterCalc, evaluator);
089                    return sumDouble(evaluator.push(), iterable, calc);
090                }
091    
092                public Calc[] getCalcs() {
093                    return new Calc[] {ncalc, calc};
094                }
095    
096                public boolean dependsOn(Dimension dimension) {
097                    return anyDependsButFirst(getCalcs(), dimension);
098                }
099            };
100        }
101    
102        protected Calc genListCalc(final ResolvedFunCall call,
103                final Calc ncalc, final Calc calc) {
104            return new AbstractDoubleCalc(call, new Calc[] {ncalc, calc}) {
105                public double evaluateDouble(Evaluator evaluator) {
106                    ListCalc listCalc = (ListCalc) ncalc;
107                    List memberList = evaluateCurrentList(listCalc, evaluator);
108                    return sumDouble(evaluator.push(), memberList, calc);
109                }
110    
111                public Calc[] getCalcs() {
112                    return new Calc[] {ncalc, calc};
113                }
114    
115                public boolean dependsOn(Dimension dimension) {
116                    return anyDependsButFirst(getCalcs(), dimension);
117                }
118            };
119        }
120    }
121    
122    // End SumFunDef.java