001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/RangeFunDef.java#15 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2002-2002 Kana Software, Inc. 007 // Copyright (C) 2002-2008 Julian Hyde and others 008 // All Rights Reserved. 009 // You must accept the terms of that agreement to use this software. 010 // 011 // jhyde, 3 March, 2002 012 */ 013 package mondrian.olap.fun; 014 import mondrian.calc.Calc; 015 import mondrian.calc.ExpCompiler; 016 import mondrian.calc.MemberCalc; 017 import mondrian.calc.impl.AbstractListCalc; 018 import mondrian.calc.impl.ConstantCalc; 019 import mondrian.mdx.ResolvedFunCall; 020 import mondrian.olap.Evaluator; 021 import mondrian.olap.Exp; 022 import mondrian.olap.Member; 023 import mondrian.olap.type.NullType; 024 import mondrian.resource.MondrianResource; 025 import mondrian.rolap.RolapMember; 026 027 import java.util.Collections; 028 import java.util.List; 029 030 /** 031 * Definition of the MDX <code><Member> : <Member></code> operator, 032 * which returns the set of members between a given pair of members. 033 * 034 * @author jhyde 035 * @since 3 March, 2002 036 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/RangeFunDef.java#15 $ 037 */ 038 class RangeFunDef extends FunDefBase { 039 static final RangeFunDef instance = new RangeFunDef(); 040 041 private RangeFunDef() { 042 super(":", "<Member> : <Member>", 043 "Infix colon operator returns the set of members between a given pair of members.", 044 "ixmm"); 045 } 046 047 048 /** 049 * return two membercalc objects, substituting null's with the hierarchy 050 * null member of the other expression. 051 * 052 * @param exp0 first expression 053 * @param exp1 second expression 054 * 055 * @return two member calcs 056 */ 057 private MemberCalc[] compileMembers(Exp exp0, Exp exp1, ExpCompiler compiler) { 058 MemberCalc[] members = new MemberCalc[2]; 059 060 if (exp0.getType() instanceof NullType) { 061 members[0] = null; 062 } else { 063 members[0] = compiler.compileMember(exp0); 064 } 065 066 if (exp1.getType() instanceof NullType) { 067 members[1] = null; 068 } else { 069 members[1] = compiler.compileMember(exp1); 070 } 071 072 // replace any null types with hierachy null member 073 // if both objects are null, throw exception 074 075 if (members[0] == null && members[1] == null) { 076 throw MondrianResource.instance().TwoNullsNotSupported.ex(); 077 } else if (members[0] == null) { 078 Member nullMember = ((RolapMember)members[1].evaluate(null)).getHierarchy().getNullMember(); 079 members[0] = (MemberCalc)ConstantCalc.constantMember(nullMember); 080 } else if (members[1] == null) { 081 Member nullMember = ((RolapMember)members[0].evaluate(null)).getHierarchy().getNullMember(); 082 members[1] = (MemberCalc)ConstantCalc.constantMember(nullMember); 083 } 084 085 return members; 086 } 087 088 public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) { 089 final MemberCalc[] memberCalcs = compileMembers(call.getArg(0), call.getArg(1), compiler); 090 return new AbstractListCalc(call, new Calc[] {memberCalcs[0], memberCalcs[1]}) { 091 public List evaluateList(Evaluator evaluator) { 092 final Member member0 = memberCalcs[0].evaluateMember(evaluator); 093 final Member member1 = memberCalcs[1].evaluateMember(evaluator); 094 if (member0.isNull() || member1.isNull()) { 095 return Collections.EMPTY_LIST; 096 } 097 if (member0.getLevel() != member1.getLevel()) { 098 throw evaluator.newEvalException( 099 call.getFunDef(), 100 "Members must belong to the same level"); 101 } 102 return FunUtil.memberRange(evaluator, member0, member1); 103 } 104 }; 105 } 106 } 107 108 // End RangeFunDef.java