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);
}
};
}
}
Aggregations