001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/AddCalculatedMembersFunDef.java#5 $ 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) 2006-2008 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.olap.fun; 011 012 import mondrian.calc.*; 013 import mondrian.calc.impl.AbstractListCalc; 014 import mondrian.mdx.ResolvedFunCall; 015 import mondrian.olap.*; 016 import mondrian.olap.type.SetType; 017 import mondrian.olap.type.MemberType; 018 import mondrian.olap.type.Type; 019 020 import java.util.*; 021 022 /** 023 * Definition of the <code>AddCalculatedMembers</code> MDX function. 024 * 025 * <p>AddCalculatedMembers adds calculated members that are siblings 026 * of the members in the set. The set is limited to one dimension. 027 * 028 * <p>Syntax: 029 * 030 * <blockquote><pre>AddCalculatedMembers(<Set>)</pre></blockquote> 031 032 * @author jhyde 033 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/AddCalculatedMembersFunDef.java#5 $ 034 * @since Mar 23, 2006 035 */ 036 class AddCalculatedMembersFunDef extends FunDefBase { 037 private static final AddCalculatedMembersFunDef instance = 038 new AddCalculatedMembersFunDef(); 039 040 public static final Resolver resolver = new ResolverImpl(); 041 private static final String FLAG = "fxx"; 042 043 private AddCalculatedMembersFunDef() { 044 super( 045 "AddCalculatedMembers", 046 "Adds calculated members to a set.", 047 FLAG); 048 } 049 050 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 051 final MemberListCalc listCalc = 052 (MemberListCalc) compiler.compileList(call.getArg(0)); 053 return new AbstractListCalc(call, new Calc[] {listCalc}) { 054 public List evaluateList(Evaluator evaluator) { 055 final List<Member> list = 056 listCalc.evaluateMemberList(evaluator); 057 return addCalculatedMembers(list, evaluator); 058 } 059 }; 060 } 061 062 private List<Member> addCalculatedMembers( 063 List<Member> memberList, 064 Evaluator evaluator) 065 { 066 // Determine unique levels in the set 067 Map<Level, Object> levelMap = new HashMap<Level, Object>(); 068 Dimension dim = null; 069 070 for (Member member : memberList) { 071 if (dim == null) { 072 dim = member.getDimension(); 073 } else if (dim != member.getDimension()) { 074 throw newEvalException(this, 075 "Only members from the same dimension are allowed in the AddCalculatedMembers set: " 076 + dim.toString() + " vs " + 077 member.getDimension().toString()); 078 } 079 if (!levelMap.containsKey(member.getLevel())) { 080 levelMap.put(member.getLevel(), null); 081 } 082 } 083 084 // For each level, add the calculated members from both 085 // the schema and the query 086 List<Member> workingList = new ArrayList<Member>(memberList); 087 final SchemaReader schemaReader = 088 evaluator.getQuery().getSchemaReader(true); 089 for (Level level : levelMap.keySet()) { 090 List<Member> calcMemberList = 091 schemaReader.getCalculatedMembers(level); 092 workingList.addAll(calcMemberList); 093 } 094 memberList = workingList; 095 return memberList; 096 } 097 098 private static class ResolverImpl extends MultiResolver { 099 public ResolverImpl() { 100 super( 101 instance.getName(), 102 instance.getSignature(), 103 instance.getDescription(), 104 new String[] {FLAG}); 105 } 106 107 protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) { 108 if (args.length == 1) { 109 Exp arg = args[0]; 110 final Type type1 = arg.getType(); 111 if (type1 instanceof SetType) { 112 SetType type = (SetType) type1; 113 if (type.getElementType() instanceof MemberType) { 114 return instance; 115 } else { 116 throw newEvalException( 117 instance, 118 "Only single dimension members allowed in set for AddCalculatedMembers"); 119 } 120 } 121 } 122 return null; 123 } 124 } 125 } 126 127 // End AddCalculatedMembersFunDef.java