Search in sources :

Example 1 with HierarchyExpr

use of mondrian.mdx.HierarchyExpr in project mondrian by pentaho.

the class DescendantsFunDef method compileCall.

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
    final Type type0 = call.getArg(0).getType();
    if (type0 instanceof SetType) {
        final SetType setType = (SetType) type0;
        if (setType.getElementType() instanceof TupleType) {
            throw MondrianResource.instance().DescendantsAppliedToSetOfTuples.ex();
        }
        MemberType memberType = (MemberType) setType.getElementType();
        final Hierarchy hierarchy = memberType.getHierarchy();
        if (hierarchy == null) {
            throw MondrianResource.instance().CannotDeduceTypeOfSet.ex();
        }
        // Convert
        // Descendants(<set>, <args>)
        // into
        // Generate(<set>, Descendants(<dimension>.CurrentMember, <args>))
        Exp[] descendantsArgs = call.getArgs().clone();
        descendantsArgs[0] = new UnresolvedFunCall("CurrentMember", Syntax.Property, new Exp[] { new HierarchyExpr(hierarchy) });
        final ResolvedFunCall generateCall = (ResolvedFunCall) compiler.getValidator().validate(new UnresolvedFunCall("Generate", new Exp[] { call.getArg(0), new UnresolvedFunCall("Descendants", descendantsArgs) }), false);
        return generateCall.accept(compiler);
    }
    final MemberCalc memberCalc = compiler.compileMember(call.getArg(0));
    Flag flag = Flag.SELF;
    if (call.getArgCount() == 1) {
        flag = Flag.SELF_BEFORE_AFTER;
    }
    final boolean depthSpecified = call.getArgCount() >= 2 && call.getArg(1).getType() instanceof NumericType;
    final boolean depthEmpty = call.getArgCount() >= 2 && call.getArg(1).getType() instanceof EmptyType;
    if (call.getArgCount() >= 3) {
        flag = FunUtil.getLiteralArg(call, 2, Flag.SELF, Flag.class);
    }
    if (call.getArgCount() >= 2 && depthEmpty) {
        if (flag != Flag.LEAVES) {
            throw Util.newError("depth must be specified unless DESC_FLAG is LEAVES");
        }
    }
    if ((depthSpecified || depthEmpty) && flag.leaves) {
        final IntegerCalc depthCalc = depthSpecified ? compiler.compileInteger(call.getArg(1)) : null;
        return new AbstractListCalc(call, new Calc[] { memberCalc, depthCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                int depth = -1;
                if (depthCalc != null) {
                    depth = depthCalc.evaluateInteger(evaluator);
                    if (depth < 0) {
                        // no limit
                        depth = -1;
                    }
                }
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                descendantsLeavesByDepth(member, result, schemaReader, depth);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    } else if (depthSpecified) {
        final IntegerCalc depthCalc = compiler.compileInteger(call.getArg(1));
        final Flag flag1 = flag;
        return new AbstractListCalc(call, new Calc[] { memberCalc, depthCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                final int depth = depthCalc.evaluateInteger(evaluator);
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                descendantsByDepth(member, result, schemaReader, depth, flag1.before, flag1.self, flag1.after, evaluator);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    } else {
        final LevelCalc levelCalc = call.getArgCount() > 1 ? compiler.compileLevel(call.getArg(1)) : null;
        final Flag flag2 = flag;
        return new AbstractListCalc(call, new Calc[] { memberCalc, levelCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Evaluator context = evaluator.isNonEmpty() ? evaluator : null;
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                final Level level = levelCalc != null ? levelCalc.evaluateLevel(evaluator) : member.getLevel();
                descendantsByLevel(schemaReader, member, level, result, flag2.before, flag2.self, flag2.after, flag2.leaves, context);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    }
}
Also used : NumericType(mondrian.olap.type.NumericType) SchemaReader(mondrian.olap.SchemaReader) EmptyType(mondrian.olap.type.EmptyType) ArrayList(java.util.ArrayList) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) UnresolvedFunCall(mondrian.mdx.UnresolvedFunCall) HierarchyExpr(mondrian.mdx.HierarchyExpr) Hierarchy(mondrian.olap.Hierarchy) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) IntegerCalc(mondrian.calc.IntegerCalc) SetType(mondrian.olap.type.SetType) TupleType(mondrian.olap.type.TupleType) ArrayList(java.util.ArrayList) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) List(java.util.List) Sorter.hierarchizeMemberList(mondrian.olap.fun.sort.Sorter.hierarchizeMemberList) Member(mondrian.olap.Member) Calc(mondrian.calc.Calc) LevelCalc(mondrian.calc.LevelCalc) MemberCalc(mondrian.calc.MemberCalc) IntegerCalc(mondrian.calc.IntegerCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) LevelCalc(mondrian.calc.LevelCalc) Evaluator(mondrian.olap.Evaluator) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) EmptyType(mondrian.olap.type.EmptyType) MemberType(mondrian.olap.type.MemberType) TupleType(mondrian.olap.type.TupleType) NumericType(mondrian.olap.type.NumericType) Type(mondrian.olap.type.Type) SetType(mondrian.olap.type.SetType) MemberType(mondrian.olap.type.MemberType) MemberCalc(mondrian.calc.MemberCalc) ResolvedFunCall(mondrian.mdx.ResolvedFunCall) Level(mondrian.olap.Level) Exp(mondrian.olap.Exp)

Aggregations

ArrayList (java.util.ArrayList)1 List (java.util.List)1 Calc (mondrian.calc.Calc)1 IntegerCalc (mondrian.calc.IntegerCalc)1 LevelCalc (mondrian.calc.LevelCalc)1 MemberCalc (mondrian.calc.MemberCalc)1 TupleList (mondrian.calc.TupleList)1 AbstractListCalc (mondrian.calc.impl.AbstractListCalc)1 UnaryTupleList (mondrian.calc.impl.UnaryTupleList)1 HierarchyExpr (mondrian.mdx.HierarchyExpr)1 ResolvedFunCall (mondrian.mdx.ResolvedFunCall)1 UnresolvedFunCall (mondrian.mdx.UnresolvedFunCall)1 Evaluator (mondrian.olap.Evaluator)1 Exp (mondrian.olap.Exp)1 Hierarchy (mondrian.olap.Hierarchy)1 Level (mondrian.olap.Level)1 Member (mondrian.olap.Member)1 SchemaReader (mondrian.olap.SchemaReader)1 Sorter.hierarchizeMemberList (mondrian.olap.fun.sort.Sorter.hierarchizeMemberList)1 EmptyType (mondrian.olap.type.EmptyType)1