/* * This software is subject to the terms of the Eclipse Public License v1.0 * Agreement, available at the following URL: * http://www.eclipse.org/legal/epl-v10.html. * You must accept the terms of that agreement to use this software. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package mondrian.olap.fun; import mondrian.calc.*; import mondrian.calc.impl.AbstractListCalc; import mondrian.calc.impl.ConstantCalc; import mondrian.mdx.ResolvedFunCall; import mondrian.olap.Evaluator; import mondrian.olap.FunDef; /** * Definition of the <code>Head</code> and <code>Tail</code> * MDX builtin functions. * * @author jhyde * @since Mar 23, 2006 */ class HeadTailFunDef extends FunDefBase { static final Resolver TailResolver = new ReflectiveMultiResolver( "Tail", "Tail(<Set>[, <Count>])", "Returns a subset from the end of a set.", new String[] {"fxx", "fxxn"}, HeadTailFunDef.class); static final Resolver HeadResolver = new ReflectiveMultiResolver( "Head", "Head(<Set>[, < Numeric Expression >])", "Returns the first specified number of elements in a set.", new String[] {"fxx", "fxxn"}, HeadTailFunDef.class); private final boolean head; public HeadTailFunDef(FunDef dummyFunDef) { super(dummyFunDef); head = dummyFunDef.getName().equals("Head"); } public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { final ListCalc listCalc = compiler.compileList(call.getArg(0)); final IntegerCalc integerCalc = call.getArgCount() > 1 ? compiler.compileInteger(call.getArg(1)) : ConstantCalc.constantInteger(1); if (head) { return new AbstractListCalc( call, new Calc[] {listCalc, integerCalc}) { public TupleList evaluateList(Evaluator evaluator) { final int savepoint = evaluator.savepoint(); try { evaluator.setNonEmpty(false); TupleList list = listCalc.evaluateList(evaluator); int count = integerCalc.evaluateInteger(evaluator); return head(count, list); } finally { evaluator.restore(savepoint); } } }; } else { return new AbstractListCalc( call, new Calc[] {listCalc, integerCalc}) { public TupleList evaluateList(Evaluator evaluator) { final int savepoint = evaluator.savepoint(); try { evaluator.setNonEmpty(false); TupleList list = listCalc.evaluateList(evaluator); int count = integerCalc.evaluateInteger(evaluator); return tail(count, list); } finally { evaluator.restore(savepoint); } } }; } } static TupleList tail(final int count, final TupleList members) { assert members != null; final int memberCount = members.size(); if (count >= memberCount) { return members; } if (count <= 0) { return TupleCollections.emptyList(members.getArity()); } return members.subList(members.size() - count, members.size()); } static TupleList head(final int count, final TupleList members) { assert members != null; if (count <= 0) { return TupleCollections.emptyList(members.getArity()); } return members.subList(0, Math.min(count, members.size())); } } // End HeadTailFunDef.java