Package mondrian.olap.fun

Source Code of mondrian.olap.fun.DrilldownLevelTopBottomFunDef

/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2007-2009 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.olap.fun;

import mondrian.olap.*;
import mondrian.olap.type.ScalarType;
import mondrian.calc.*;
import mondrian.calc.impl.AbstractListCalc;
import mondrian.calc.impl.ValueCalc;
import mondrian.mdx.ResolvedFunCall;

import java.util.*;

/**
* Definition of the <code>DrilldownLevelTop</code> and
* <code>DrilldownLevelBottom</code> MDX builtin functions.
*
* <p>Syntax:
*
* <blockquote>
* DrilldownLevelTop(Set_Expression, Count [, [Level_Expression][,
* Numeric_Expression]])<br/>
* DrilldownLevelBottom(Set_Expression, Count [, [Level_Expression][,
* Numeric_Expression]])
* </blockquote>
*
* @author jhyde
* @version $Id: //open/mondrian-release/3.2/src/main/mondrian/olap/fun/DrilldownLevelTopBottomFunDef.java#1 $
* @since Oct 18, 2007
*/
class DrilldownLevelTopBottomFunDef extends FunDefBase {
    final boolean top;

    static final MultiResolver DrilldownLevelTopResolver = new MultiResolver(
            "DrilldownLevelTop",
            "DrilldownLevelTop(Set_Expression, Count [, [Level_Expression][, Numeric_Expression]])",
            "Drills down the topmost members of a set, at a specified level, to one level below.",
            new String[] {"fxxn", "fxxnl", "fxxnln", "fxxnen"}) {
        protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
            return new DrilldownLevelTopBottomFunDef(dummyFunDef, true);
        }
    };

    static final MultiResolver DrilldownLevelBottomResolver = new MultiResolver(
            "DrilldownLevelBottom",
            "DrilldownLevelBottom(Set_Expression, Count [, [Level_Expression][, Numeric_Expression]])",
            "Drills down the bottommost members of a set, at a specified level, to one level below.",
            new String[] {"fxxn", "fxxnl", "fxxnln", "fxxnen"}) {
        protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
            return new DrilldownLevelTopBottomFunDef(dummyFunDef, false);
        }
    };

    public DrilldownLevelTopBottomFunDef(
        FunDef dummyFunDef,
        final boolean top)
    {
        super(dummyFunDef);
        this.top = top;
    }

    public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
        // Compile the member list expression. Ask for a mutable list, because
        // we're going to insert members into it later.
        final ListCalc listCalc =
            compiler.compileList(call.getArg(0), true);
        final IntegerCalc integerCalc =
            compiler.compileInteger(call.getArg(1));
        final LevelCalc levelCalc =
            call.getArgCount() > 2
                && call.getArg(2).getCategory() != Category.Empty
                ? compiler.compileLevel(call.getArg(2))
                : null;
        final Calc orderCalc =
            call.getArgCount() > 3
            ? compiler.compileScalar(call.getArg(3), true)
            : new ValueCalc(
                new DummyExp(
                    new ScalarType()));
        return new AbstractListCalc(
            call,
            new Calc[] {listCalc, integerCalc, orderCalc})
        {
            public List evaluateList(Evaluator evaluator) {
                // Use a native evaluator, if more efficient.
                // TODO: Figure this out at compile time.
                SchemaReader schemaReader = evaluator.getSchemaReader();
                NativeEvaluator nativeEvaluator =
                    schemaReader.getNativeSetEvaluator(
                        call.getFunDef(), call.getArgs(), evaluator, this);
                if (nativeEvaluator != null) {
                    return (List) nativeEvaluator.execute(ResultStyle.LIST);
                }

                List<Member> list = listCalc.evaluateList(evaluator);
                int n = integerCalc.evaluateInteger(evaluator);
                if (n == FunUtil.IntegerNull || n <= 0) {
                    return list;
                }
                Level level;
                if (levelCalc == null) {
                    level = null;
                } else {
                    level = levelCalc.evaluateLevel(evaluator);
                }
                List<Member> result = new ArrayList<Member>();
                for (Member member : list) {
                    result.add(member);
                    if (level != null && member.getLevel() != level) {
                        if (level.getDimension() != member.getDimension()) {
                            throw newEvalException(
                                DrilldownLevelTopBottomFunDef.this,
                                "Level '"
                                    + level.getUniqueName()
                                    + "' not compatible with member '"
                                    + member.getUniqueName()
                                    + "'");
                        }
                        continue;
                    }
                    List<Member> children =
                        schemaReader.getMemberChildren(member);
                    final List<Member> sortedChildren =
                        sortMembers(
                            evaluator.push(false),
                            children,
                            children,
                            orderCalc,
                            top,
                            true);
                    int x = Math.min(n, sortedChildren.size());
                    for (int i = 0; i < x; i++) {
                        result.add(sortedChildren.get(i));
                    }
                }
                return result;
            }

            public boolean dependsOn(Hierarchy hierarchy) {
                return anyDependsButFirst(getCalcs(), hierarchy);
            }
        };
    }
}

// End DrilldownLevelTopBottomFunDef.java
TOP

Related Classes of mondrian.olap.fun.DrilldownLevelTopBottomFunDef

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.