001 /*
002 // $Id: //open/mondrian-release/3.1/src/main/mondrian/olap/fun/NonEmptyCrossJoinFunDef.java#2 $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2005-2009 Julian Hyde and others
007 // Copyright (C) 2004-2005 SAS Institute, Inc.
008 // All Rights Reserved.
009 // You must accept the terms of that agreement to use this software.
010 //
011 // sasebb, 16 December, 2004
012 */
013 package mondrian.olap.fun;
014
015 import java.util.List;
016 import java.util.Collections;
017
018 import mondrian.olap.*;
019 import mondrian.calc.*;
020 import mondrian.calc.impl.AbstractListCalc;
021 import mondrian.mdx.ResolvedFunCall;
022
023
024 /**
025 * Definition of the <code>NonEmptyCrossJoin</code> MDX function.
026 *
027 * @author jhyde
028 * @version $Id: //open/mondrian-release/3.1/src/main/mondrian/olap/fun/NonEmptyCrossJoinFunDef.java#2 $
029 * @since Mar 23, 2006
030 */
031 public class NonEmptyCrossJoinFunDef extends CrossJoinFunDef {
032 static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
033 "NonEmptyCrossJoin",
034 "NonEmptyCrossJoin(<Set1>, <Set2>)",
035 "Returns the cross product of two sets, excluding empty tuples and tuples without associated fact table data.",
036 new String[]{"fxxx"},
037 NonEmptyCrossJoinFunDef.class);
038
039 public NonEmptyCrossJoinFunDef(FunDef dummyFunDef) {
040 super(dummyFunDef);
041 }
042
043 public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
044 final ListCalc listCalc1 = compiler.compileList(call.getArg(0));
045 final ListCalc listCalc2 = compiler.compileList(call.getArg(1));
046 return new AbstractListCalc(
047 call, new Calc[] {listCalc1, listCalc2}, false)
048 {
049 public List evaluateList(Evaluator evaluator) {
050 SchemaReader schemaReader = evaluator.getSchemaReader();
051 // evaluate the arguments in non empty mode
052 evaluator = evaluator.push(true);
053 NativeEvaluator nativeEvaluator =
054 schemaReader.getNativeSetEvaluator(
055 call.getFunDef(), call.getArgs(), evaluator, this);
056 if (nativeEvaluator != null) {
057 return (List) nativeEvaluator.execute(ResultStyle.LIST);
058 }
059
060 final List list1 = listCalc1.evaluateList(evaluator);
061 if (list1.isEmpty()) {
062 return Collections.EMPTY_LIST;
063 }
064 final List list2 = listCalc2.evaluateList(evaluator);
065 List<Member[]> result = crossJoin(list1, list2);
066
067 // remove any remaining empty crossings from the result
068 result = nonEmptyList(evaluator, result, call);
069 return result;
070 }
071
072 public boolean dependsOn(Dimension dimension) {
073 if (super.dependsOn(dimension)) {
074 return true;
075 }
076 // Member calculations generate members, which mask the actual
077 // expression from the inherited context.
078 if (listCalc1.getType().usesDimension(dimension, true)) {
079 return false;
080 }
081 if (listCalc2.getType().usesDimension(dimension, true)) {
082 return false;
083 }
084 // The implicit value expression, executed to figure out
085 // whether a given tuple is empty, depends upon all dimensions.
086 return true;
087 }
088 };
089 }
090
091 }
092
093 // End NonEmptyCrossJoinFunDef.java