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