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