001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/fun/XtdFunDef.java#13 $ 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) 2005-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.*; 013 import mondrian.olap.type.Type; 014 import mondrian.olap.type.SetType; 015 import mondrian.olap.type.MemberType; 016 import mondrian.resource.MondrianResource; 017 import mondrian.calc.*; 018 import mondrian.calc.impl.AbstractListCalc; 019 import mondrian.mdx.ResolvedFunCall; 020 021 import java.util.List; 022 023 /** 024 * Definition of <code>Ytd</code>, <code>Qtd</code>, <code>Mtd</code>, 025 * and <code>Wtd</code> MDX builtin functions. 026 * 027 * @author jhyde 028 * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/XtdFunDef.java#13 $ 029 * @since Mar 23, 2006 030 */ 031 class XtdFunDef extends FunDefBase { 032 private final LevelType levelType; 033 034 static final ResolverImpl MtdResolver = new ResolverImpl( 035 "Mtd", 036 "Mtd([<Member>])", 037 "A shortcut function for the PeriodsToDate function that specifies the level to be Month.", 038 new String[]{"fx", "fxm"}, 039 LevelType.TimeMonths); 040 041 static final ResolverImpl QtdResolver = new ResolverImpl( 042 "Qtd", 043 "Qtd([<Member>])", 044 "A shortcut function for the PeriodsToDate function that specifies the level to be Quarter.", 045 new String[]{"fx", "fxm"}, 046 LevelType.TimeQuarters); 047 048 static final ResolverImpl WtdResolver = new ResolverImpl( 049 "Wtd", 050 "Wtd([<Member>])", 051 "A shortcut function for the PeriodsToDate function that specifies the level to be Week.", 052 new String[]{"fx", "fxm"}, 053 LevelType.TimeWeeks); 054 055 static final ResolverImpl YtdResolver = new ResolverImpl( 056 "Ytd", 057 "Ytd([<Member>])", 058 "A shortcut function for the PeriodsToDate function that specifies the level to be Year.", 059 new String[]{"fx", "fxm"}, 060 LevelType.TimeYears); 061 062 public XtdFunDef(FunDef dummyFunDef, LevelType levelType) { 063 super(dummyFunDef); 064 this.levelType = levelType; 065 } 066 067 public Type getResultType(Validator validator, Exp[] args) { 068 if (args.length == 0) { 069 // With no args, the default implementation cannot 070 // guess the hierarchy. 071 Dimension defaultTimeDimension = 072 validator.getQuery().getCube().getTimeDimension(); 073 if (defaultTimeDimension == null) { 074 throw MondrianResource.instance(). 075 NoTimeDimensionInCube.ex(getName()); 076 } 077 Hierarchy hierarchy = defaultTimeDimension.getHierarchy(); 078 return new SetType(MemberType.forHierarchy(hierarchy)); 079 } 080 final Type type = args[0].getType(); 081 if (type.getHierarchy().getDimension() 082 .getDimensionType() != 083 DimensionType.TimeDimension) { 084 throw MondrianResource.instance().TimeArgNeeded.ex(getName()); 085 } 086 return super.getResultType(validator, args); 087 } 088 089 private Level getLevel(Evaluator evaluator) { 090 switch (levelType) { 091 case TimeYears: 092 return evaluator.getCube().getYearLevel(); 093 case TimeQuarters: 094 return evaluator.getCube().getQuarterLevel(); 095 case TimeMonths: 096 return evaluator.getCube().getMonthLevel(); 097 case TimeWeeks: 098 return evaluator.getCube().getWeekLevel(); 099 case TimeDays: 100 return evaluator.getCube().getWeekLevel(); 101 default: 102 throw Util.badValue(levelType); 103 } 104 } 105 106 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 107 final Level level = getLevel(compiler.getEvaluator()); 108 switch (call.getArgCount()) { 109 case 0: 110 return new AbstractListCalc(call, new Calc[0]) { 111 public List evaluateList(Evaluator evaluator) { 112 return periodsToDate(evaluator, level, null); 113 } 114 115 public boolean dependsOn(Dimension dimension) { 116 return dimension.getDimensionType() == 117 mondrian.olap.DimensionType.TimeDimension; 118 } 119 }; 120 default: 121 final MemberCalc memberCalc = 122 compiler.compileMember(call.getArg(0)); 123 return new AbstractListCalc(call, new Calc[] {memberCalc}) { 124 public List evaluateList(Evaluator evaluator) { 125 return periodsToDate(evaluator, level, 126 memberCalc.evaluateMember(evaluator)); 127 } 128 }; 129 } 130 } 131 132 private static class ResolverImpl extends MultiResolver { 133 private final LevelType levelType; 134 135 public ResolverImpl( 136 String name, 137 String signature, 138 String description, 139 String[] signatures, 140 LevelType levelType) { 141 super(name, signature, description, signatures); 142 this.levelType = levelType; 143 } 144 145 protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) { 146 return new XtdFunDef(dummyFunDef, levelType); 147 } 148 }; 149 } 150 151 // End XtdFunDef.java