001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/IntersectFunDef.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-2002 Kana Software, Inc. 007 // Copyright (C) 2004-2007 Julian Hyde and others 008 // All Rights Reserved. 009 // You must accept the terms of that agreement to use this software. 010 */ 011 package mondrian.olap.fun; 012 013 import mondrian.olap.*; 014 import mondrian.calc.*; 015 import mondrian.calc.impl.AbstractListCalc; 016 import mondrian.mdx.ResolvedFunCall; 017 018 import java.util.*; 019 020 /** 021 * Definition of the <code>INTERSECT</code> MDX function. 022 * 023 * @author jhyde 024 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/IntersectFunDef.java#12 $ 025 * @since Mar 23, 2006 026 */ 027 class IntersectFunDef extends FunDefBase 028 { 029 private static final String[] ReservedWords = new String[] {"ALL"}; 030 031 static final Resolver resolver = new ReflectiveMultiResolver( 032 "Intersect", 033 "Intersect(<Set1>, <Set2>[, ALL])", 034 "Returns the intersection of two input sets, optionally retaining duplicates.", 035 new String[] {"fxxxy", "fxxx"}, 036 IntersectFunDef.class, 037 ReservedWords); 038 039 public IntersectFunDef(FunDef dummyFunDef) 040 { 041 super(dummyFunDef); 042 } 043 044 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 045 final ListCalc listCalc1 = compiler.compileList(call.getArg(0)); 046 final ListCalc listCalc2 = compiler.compileList(call.getArg(1)); 047 final String literalArg = getLiteralArg(call, 2, "", ReservedWords); 048 final boolean all = literalArg.equalsIgnoreCase("ALL"); 049 050 // todo: optimize for member lists vs. tuple lists 051 return new AbstractListCalc(call, new Calc[] {listCalc1, listCalc2}) { 052 public List evaluateList(Evaluator evaluator) { 053 List left = listCalc1.evaluateList(evaluator); 054 if (left == null || left.isEmpty()) { 055 return Collections.EMPTY_LIST; 056 } 057 Collection right = listCalc2.evaluateList(evaluator); 058 if (right == null || right.isEmpty()) { 059 return Collections.EMPTY_LIST; 060 } 061 right = buildSearchableCollection(right); 062 List result = new ArrayList(); 063 064 for (Object leftObject : left) { 065 Object resultObject = leftObject; 066 067 if (leftObject instanceof Object[]) { 068 leftObject = new ArrayHolder((Object[]) leftObject); 069 } 070 071 if (right.contains(leftObject)) { 072 if (all || !result.contains(leftObject)) { 073 result.add(resultObject); 074 } 075 } 076 } 077 return result; 078 } 079 }; 080 } 081 082 private static Collection buildSearchableCollection(Collection right) { 083 Iterator iter = right.iterator(); 084 Set result = new HashSet(right.size(), 1); 085 while (iter.hasNext()) { 086 Object element = iter.next(); 087 088 if (element instanceof Object[]) { 089 element = new ArrayHolder((Object[])element); 090 } 091 092 result.add(element); 093 } 094 095 return result; 096 } 097 } 098 099 // End IntersectFunDef.java