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-2010 Pentaho and others 008// All Rights Reserved. 009*/ 010package mondrian.udf; 011 012import mondrian.olap.*; 013import mondrian.olap.type.*; 014import mondrian.spi.UserDefinedFunction; 015import mondrian.util.Format; 016 017import java.util.*; 018 019/** 020 * User-defined function <code>CurrentDateMember</code>. Arguments to the 021 * function are as follows: 022 * 023 * <blockquote> 024 * <code> 025 * CurrentDateMember(<Hierarchy>, <FormatString>[, <Find>) 026 * returns <Member> 027 * </code> 028 * </blockquote> 029 * 030 * The function returns the member from the specified hierarchy that matches 031 * the current date, to the granularity specified by the <FormatString>. 032 * 033 * The format string conforms to the format string implemented by 034 * {@link Format}. 035 * 036 * @author Zelaine Fong 037 */ 038public class CurrentDateMemberUdf implements UserDefinedFunction { 039 private Object resultDateMember = null; 040 041 public Object execute(Evaluator evaluator, Argument[] arguments) { 042 if (resultDateMember != null) { 043 return resultDateMember; 044 } 045 046 // determine the current date 047 Object formatArg = arguments[1].evaluateScalar(evaluator); 048 049 final Locale locale = Locale.getDefault(); 050 final Format format = new Format((String) formatArg, locale); 051 String currDateStr = format.format(getDate(evaluator, arguments)); 052 053 // determine the match type 054 MatchType matchType; 055 if (arguments.length == 3) { 056 String matchStr = arguments[2].evaluateScalar(evaluator).toString(); 057 matchType = Enum.valueOf(MatchType.class, matchStr); 058 } else { 059 matchType = MatchType.EXACT; 060 } 061 062 List<Id.Segment> uniqueNames = Util.parseIdentifier(currDateStr); 063 resultDateMember = 064 evaluator.getSchemaReader().getMemberByUniqueName( 065 uniqueNames, false, matchType); 066 if (resultDateMember != null) { 067 return resultDateMember; 068 } 069 070 // if there is no matching member, return the null member for 071 // the specified dimension/hierarchy 072 Object arg0 = arguments[0].evaluate(evaluator); 073 if (arg0 instanceof Hierarchy) { 074 resultDateMember = ((Hierarchy) arg0).getNullMember(); 075 } else { 076 resultDateMember = 077 ((Dimension) arg0).getHierarchy().getNullMember(); 078 } 079 return resultDateMember; 080 } 081 082 /* 083 * Package private function created for proper testing. 084 */ 085 Date getDate(Evaluator evaluator, Argument[] arguments) { 086 return evaluator.getQueryStartTime(); 087 } 088 089 public String getDescription() { 090 return "Returns the closest or exact member within the specified " 091 + "dimension corresponding to the current date, in the format " 092 + "specified by the format parameter. " 093 + "Format strings are the same as used by the MDX Format function, " 094 + "namely the Visual Basic format strings. " 095 + "See http://www.apostate.com/programming/vb-format.html."; 096 } 097 098 public String getName() { 099 return "CurrentDateMember"; 100 } 101 102 public Type[] getParameterTypes() { 103 return new Type[] { 104 new HierarchyType(null, null), 105 new StringType(), 106 new SymbolType() 107 }; 108 } 109 110 public String[] getReservedWords() { 111 return new String[] { 112 "EXACT", 113 "BEFORE", 114 "AFTER" 115 }; 116 } 117 118 public Type getReturnType(Type[] parameterTypes) { 119 return MemberType.Unknown; 120 } 121 122 public Syntax getSyntax() { 123 return Syntax.Function; 124 } 125} 126 127// End CurrentDateMemberUdf.java