001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/DrilldownMemberFunDef.java#12 $ 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) 2004-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.olap.*; 013 import mondrian.calc.*; 014 import mondrian.calc.impl.AbstractListCalc; 015 import mondrian.mdx.ResolvedFunCall; 016 017 import java.util.HashSet; 018 import java.util.Set; 019 import java.util.List; 020 import java.util.ArrayList; 021 022 /** 023 * Definition of the <code>DrilldownMember</code> MDX function. 024 * 025 * @author Grzegorz Lojek 026 * @since 6 December, 2004 027 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/DrilldownMemberFunDef.java#12 $ 028 */ 029 class DrilldownMemberFunDef extends FunDefBase { 030 static final String[] reservedWords = new String[] {"RECURSIVE"}; 031 static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver( 032 "DrilldownMember", 033 "DrilldownMember(<Set1>, <Set2>[, RECURSIVE])", 034 "Drills down the members in a set that are present in a second specified set.", 035 new String[]{"fxxx", "fxxxy"}, 036 DrilldownMemberFunDef.class, 037 reservedWords); 038 039 public DrilldownMemberFunDef(FunDef funDef) { 040 super(funDef); 041 } 042 043 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 044 final ListCalc listCalc1 = compiler.compileList(call.getArg(0)); 045 final ListCalc listCalc2 = compiler.compileList(call.getArg(1)); 046 final String literalArg = getLiteralArg(call, 2, "", reservedWords); 047 final boolean recursive = literalArg.equals("RECURSIVE"); 048 049 return new AbstractListCalc(call, new Calc[] {listCalc1, listCalc2}) { 050 public List evaluateList(Evaluator evaluator) { 051 final List<?> list1 = listCalc1.evaluateList(evaluator); 052 final List<Member> list2 = listCalc2.evaluateList(evaluator); 053 return drilldownMember(list1, list2, evaluator); 054 } 055 056 /** 057 * Drills down an element. 058 * 059 * Algorithm: If object is present in a_hsSet1 then adds to result children 060 * of the object. If flag a_bRecursive is set then this method is called 061 * recursively for the children. 062 * 063 * @param element Element of a set, can be either {@link Member} or 064 * {@link Member}[] 065 * 066 * 067 */ 068 protected void drillDownObj( 069 Evaluator evaluator, 070 Object element, 071 Set memberSet, 072 List<Object> resultList) { 073 if (null == element) { 074 return; 075 } 076 077 Member m = null; 078 Member[] tuple; 079 int k = -1; 080 if (element instanceof Member) { 081 m = (Member) element; 082 if (!memberSet.contains(m)) { 083 return; 084 } 085 tuple = null; 086 } else { 087 Util.assertTrue(element instanceof Member[]); 088 tuple = (Member[]) element; 089 m = null; 090 for (Member member : tuple) { 091 ++k; 092 if (memberSet.contains(member)) { 093 m = member; 094 break; 095 } 096 } 097 if (m == null) { 098 //not found 099 return; 100 } 101 } 102 103 List<Member> children = evaluator.getSchemaReader().getMemberChildren(m); 104 for (Member member : children) { 105 Object objNew; 106 if (tuple == null) { 107 objNew = member; 108 } else { 109 Member[] members = tuple.clone(); 110 members[k] = member; 111 objNew = members; 112 } 113 114 resultList.add(objNew); 115 if (recursive) { 116 drillDownObj(evaluator, objNew, memberSet, resultList); 117 } 118 } 119 } 120 121 private List drilldownMember(List<?> v0, List<Member> v1, Evaluator evaluator) { 122 if (null == v0 || 123 v0.isEmpty() || 124 null == v1 || 125 v1.isEmpty()) { 126 return v0; 127 } 128 129 Set<Member> set1 = new HashSet<Member>(); 130 set1.addAll(v1); 131 132 List<Object> result = new ArrayList<Object>(); 133 int i = 0, n = v0.size(); 134 while (i < n) { 135 Object o = v0.get(i++); 136 result.add(o); 137 drillDownObj(evaluator, o, set1, result); 138 } 139 return result; 140 } 141 }; 142 } 143 } 144 145 // End DrilldownMemberFunDef.java