001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/UnionFunDef.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.olap.FunDef; 013 import mondrian.olap.Evaluator; 014 import mondrian.calc.Calc; 015 import mondrian.calc.ExpCompiler; 016 import mondrian.calc.ListCalc; 017 import mondrian.calc.impl.AbstractListCalc; 018 import mondrian.mdx.ResolvedFunCall; 019 020 import java.util.List; 021 import java.util.Set; 022 import java.util.HashSet; 023 import java.util.ArrayList; 024 025 /** 026 * Definition of the <code>Union</code> MDX function. 027 * 028 * @author jhyde 029 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/UnionFunDef.java#5 $ 030 * @since Mar 23, 2006 031 */ 032 class UnionFunDef extends FunDefBase { 033 static final String[] ReservedWords = new String[] {"ALL", "DISTINCT"}; 034 035 static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver( 036 "Union", 037 "Union(<Set1>, <Set2>[, ALL])", 038 "Returns the union of two sets, optionally retaining duplicates.", 039 new String[] {"fxxx", "fxxxy"}, 040 UnionFunDef.class, 041 ReservedWords); 042 043 public UnionFunDef(FunDef dummyFunDef) { 044 super(dummyFunDef); 045 } 046 047 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 048 String allString = getLiteralArg(call, 2, "DISTINCT", ReservedWords); 049 final boolean all = allString.equalsIgnoreCase("ALL"); 050 checkCompatible(call.getArg(0), call.getArg(1), null); // todo: do at validate time 051 final ListCalc listCalc0 = 052 compiler.compileList(call.getArg(0)); 053 final ListCalc listCalc1 = 054 compiler.compileList(call.getArg(1)); 055 return new AbstractListCalc(call, new Calc[] {listCalc0, listCalc1}) { 056 public List evaluateList(Evaluator evaluator) { 057 List list0 = listCalc0.evaluateList(evaluator); 058 List list1 = listCalc1.evaluateList(evaluator); 059 return union(list0, list1, all); 060 } 061 }; 062 } 063 064 <T> List<T> union(List<T> list0, List<T> list1, final boolean all) { 065 assert list0 != null; 066 assert list1 != null; 067 if (all) { 068 if (list0.isEmpty()) { 069 return list1; 070 } 071 if (list1.isEmpty()) { 072 return list0; 073 } 074 List<T> result = new ArrayList<T>(); 075 result.addAll(list0); 076 result.addAll(list1); 077 return result; 078 } else { 079 Set<Object> added = new HashSet<Object>(); 080 List<T> result = new ArrayList<T>(); 081 FunUtil.addUnique(result, list0, added); 082 FunUtil.addUnique(result, list1, added); 083 return result; 084 } 085 } 086 } 087 088 // End UnionFunDef.java