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) 2012-2013 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.olap.fun; 011 012import mondrian.calc.*; 013import mondrian.calc.impl.AbstractListCalc; 014import mondrian.mdx.ResolvedFunCall; 015import mondrian.olap.*; 016import mondrian.olap.type.LevelType; 017import mondrian.olap.type.Type; 018 019import java.util.ArrayList; 020import java.util.List; 021 022 023/** 024 * Definition of the <code>Ancestors</code> MDX function. 025 * 026 * @author lboudreau 027 * @since Nov 27 2012 028 */ 029class AncestorsFunDef extends FunDefBase { 030 static final ReflectiveMultiResolver Resolver = 031 new ReflectiveMultiResolver( 032 "Ancestors", 033 "Ancestors(<Member>, {<Level>|<Numeric Expression>})", 034 "Returns the set of all ancestors of a specified member at a specified level or at a specified distance from the member", 035 new String[] {"fxml", "fxmn"}, 036 AncestorsFunDef.class); 037 038 public AncestorsFunDef(FunDef dummyFunDef) { 039 super(dummyFunDef); 040 } 041 042 public int getReturnCategory() { 043 return Category.Set; 044 } 045 046 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 047 final MemberCalc memberCalc = 048 compiler.compileMember(call.getArg(0)); 049 final Type type1 = call.getArg(1).getType(); 050 if (type1 instanceof LevelType) { 051 final LevelCalc levelCalc = 052 compiler.compileLevel(call.getArg(1)); 053 return new AbstractListCalc( 054 call, new Calc[] {memberCalc, levelCalc}) 055 { 056 public TupleList evaluateList(Evaluator evaluator) { 057 Level level = levelCalc.evaluateLevel(evaluator); 058 Member member = memberCalc.evaluateMember(evaluator); 059 int distance = 060 member.getDepth() - level.getDepth(); 061 List<Member> ancestors = new ArrayList<Member>(); 062 for (int curDist = 1; curDist <= distance; curDist++) { 063 ancestors.add( 064 ancestor(evaluator, member, curDist, null)); 065 } 066 return TupleCollections.asTupleList(ancestors); 067 } 068 }; 069 } else { 070 final IntegerCalc distanceCalc = 071 compiler.compileInteger(call.getArg(1)); 072 return new AbstractListCalc( 073 call, new Calc[] {memberCalc, distanceCalc}) 074 { 075 public TupleList evaluateList(Evaluator evaluator) { 076 Member member = memberCalc.evaluateMember(evaluator); 077 int distance = distanceCalc.evaluateInteger(evaluator); 078 List<Member> ancestors = new ArrayList<Member>(); 079 for (int curDist = 1; curDist <= distance; curDist++) { 080 ancestors.add( 081 ancestor(evaluator, member, curDist, null)); 082 } 083 return TupleCollections.asTupleList(ancestors); 084 } 085 }; 086 } 087 } 088} 089 090// End AncestorsFunDef.java