001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/CountFunDef.java#7 $
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-2008 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.FunDef;
013    import mondrian.olap.Literal;
014    import mondrian.olap.Evaluator;
015    import mondrian.olap.Dimension;
016    import mondrian.calc.*;
017    import mondrian.calc.impl.AbstractIntegerCalc;
018    import mondrian.mdx.ResolvedFunCall;
019    
020    import java.util.List;
021    
022    /**
023     * Definition of the <code>Count</code> MDX function.
024     *
025     * @author jhyde
026     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/CountFunDef.java#7 $
027     * @since Mar 23, 2006
028     */
029    class CountFunDef extends AbstractAggregateFunDef {
030        static final String[] ReservedWords = new String[] {"INCLUDEEMPTY", "EXCLUDEEMPTY"};
031    
032        static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
033                "Count",
034                "Count(<Set>[, EXCLUDEEMPTY | INCLUDEEMPTY])",
035                "Returns the number of tuples in a set, empty cells included unless the optional EXCLUDEEMPTY flag is used.",
036                new String[]{"fnx", "fnxy"},
037                CountFunDef.class,
038                ReservedWords);
039    
040        public CountFunDef(FunDef dummyFunDef) {
041            super(dummyFunDef);
042        }
043    
044        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
045            final Calc calc =
046                compiler.compileAs(
047                    call.getArg(0), null, ResultStyle.ITERABLE_ANY);
048            final boolean includeEmpty =
049                    call.getArgCount() < 2 ||
050                    ((Literal) call.getArg(1)).getValue().equals(
051                            "INCLUDEEMPTY");
052            return new AbstractIntegerCalc(
053                    call, new Calc[] {calc}) {
054                public int evaluateInteger(Evaluator evaluator) {
055    /*
056                    if (calc instanceof ListCalc) {
057                        ListCalc listCalc = (ListCalc) calc;
058                        List memberList = evaluateCurrentList(listCalc, evaluator);
059                        return count(evaluator, memberList, includeEmpty);
060                    } else {
061                        // must be IterCalc
062                        IterCalc iterCalc = (IterCalc) calc;
063                        Iterable iterable =
064                            evaluateCurrentIterable(iterCalc, evaluator);
065                        return count(evaluator, iterable, includeEmpty);
066                    }
067    */
068                    if (calc instanceof IterCalc) {
069                        IterCalc iterCalc = (IterCalc) calc;
070                        Iterable iterable =
071                            evaluateCurrentIterable(iterCalc, evaluator);
072                        return count(evaluator, iterable, includeEmpty);
073                    } else {
074                        // must be ListCalc
075                        ListCalc listCalc = (ListCalc) calc;
076                        List memberList = evaluateCurrentList(listCalc, evaluator);
077                        return count(evaluator, memberList, includeEmpty);
078                    }
079                }
080    
081                public boolean dependsOn(Dimension dimension) {
082                    // COUNT(<set>, INCLUDEEMPTY) is straightforward -- it
083                    // depends only on the dimensions that <Set> depends
084                    // on.
085                    if (super.dependsOn(dimension)) {
086                        return true;
087                    }
088                    if (includeEmpty) {
089                        return false;
090                    }
091                    // COUNT(<set>, EXCLUDEEMPTY) depends only on the
092                    // dimensions that <Set> depends on, plus all
093                    // dimensions not masked by the set.
094                    return ! calc.getType().usesDimension(dimension, true);
095                }
096            };
097    
098    /*
099     RME OLD STUFF
100            final ListCalc memberListCalc =
101                    compiler.compileList(call.getArg(0));
102            final boolean includeEmpty =
103                    call.getArgCount() < 2 ||
104                    ((Literal) call.getArg(1)).getValue().equals(
105                            "INCLUDEEMPTY");
106            return new AbstractIntegerCalc(
107                    call, new Calc[] {memberListCalc}) {
108                public int evaluateInteger(Evaluator evaluator) {
109                    List memberList =
110                        evaluateCurrentList(memberListCalc, evaluator);
111                    return count(evaluator, memberList, includeEmpty);
112                }
113    
114                public boolean dependsOn(Dimension dimension) {
115                    // COUNT(<set>, INCLUDEEMPTY) is straightforward -- it
116                    // depends only on the dimensions that <Set> depends
117                    // on.
118                    if (super.dependsOn(dimension)) {
119                        return true;
120                    }
121                    if (includeEmpty) {
122                        return false;
123                    }
124                    // COUNT(<set>, EXCLUDEEMPTY) depends only on the
125                    // dimensions that <Set> depends on, plus all
126                    // dimensions not masked by the set.
127                    if (memberListCalc.getType().usesDimension(dimension, true)) {
128                        return false;
129                    }
130                    return true;
131                }
132            };
133    */
134        }
135    }
136    
137    // End CountFunDef.java