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