001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2006-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.olap.fun; 011 012import mondrian.calc.*; 013import mondrian.calc.impl.AbstractListCalc; 014import mondrian.mdx.ResolvedFunCall; 015import mondrian.olap.Evaluator; 016import mondrian.olap.FunDef; 017 018/** 019 * Definition of the <code>Subset</code> MDX function. 020 * 021 * @author jhyde 022 * @since Mar 23, 2006 023 */ 024class SubsetFunDef extends FunDefBase { 025 static final ReflectiveMultiResolver Resolver = 026 new ReflectiveMultiResolver( 027 "Subset", 028 "Subset(<Set>, <Start>[, <Count>])", 029 "Returns a subset of elements from a set.", 030 new String[] {"fxxn", "fxxnn"}, 031 SubsetFunDef.class); 032 033 public SubsetFunDef(FunDef dummyFunDef) { 034 super(dummyFunDef); 035 } 036 037 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 038 final ListCalc listCalc = 039 compiler.compileList(call.getArg(0)); 040 final IntegerCalc startCalc = 041 compiler.compileInteger(call.getArg(1)); 042 final IntegerCalc countCalc = 043 call.getArgCount() > 2 044 ? compiler.compileInteger(call.getArg(2)) 045 : null; 046 return new AbstractListCalc( 047 call, new Calc[] {listCalc, startCalc, countCalc}) 048 { 049 public TupleList evaluateList(Evaluator evaluator) { 050 final int savepoint = evaluator.savepoint(); 051 try { 052 evaluator.setNonEmpty(false); 053 final TupleList list = listCalc.evaluateList(evaluator); 054 final int start = startCalc.evaluateInteger(evaluator); 055 int end; 056 if (countCalc != null) { 057 final int count = countCalc.evaluateInteger(evaluator); 058 end = start + count; 059 } else { 060 end = list.size(); 061 } 062 if (end > list.size()) { 063 end = list.size(); 064 } 065 if (start >= end || start < 0) { 066 return TupleCollections.emptyList(list.getArity()); 067 } 068 if (start == 0 && end == list.size()) { 069 return list; 070 } 071 assert 0 <= start; 072 assert start < end; 073 assert end <= list.size(); 074 return list.subList(start, end); 075 } finally { 076 evaluator.restore(savepoint); 077 } 078 } 079 }; 080 } 081} 082 083// End SubsetFunDef.java