001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/CacheFunDef.java#9 $
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-2007 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.olap.fun;
011    
012    import mondrian.olap.*;
013    import mondrian.olap.type.Type;
014    import mondrian.olap.type.SetType;
015    import mondrian.calc.*;
016    import mondrian.calc.impl.GenericCalc;
017    import mondrian.mdx.ResolvedFunCall;
018    
019    import java.io.PrintWriter;
020    
021    /**
022     * Definition of the <code>Cache</code> system function, which is smart enough
023     * to evaluate its argument only once.
024     *
025     * @author jhyde
026     * @since 2005/8/14
027     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/CacheFunDef.java#9 $
028     */
029    public class CacheFunDef extends FunDefBase {
030        static final String NAME = "Cache";
031        private static final String SIGNATURE = "Cache(<<Exp>>)";
032        private static final String DESCRIPTION = "Evaluates and returns its sole argument, applying statement-level caching";
033        private static final Syntax SYNTAX = Syntax.Function;
034        static final CacheFunResolver Resolver = new CacheFunResolver();
035    
036        CacheFunDef(
037                String name,
038                String signature,
039                String description,
040                Syntax syntax,
041                int category,
042                Type type) {
043            super(name, signature, description, syntax,
044                    category, new int[] {category});
045            Util.discard(type);
046        }
047    
048        public void unparse(Exp[] args, PrintWriter pw) {
049            args[0].unparse(pw);
050        }
051    
052        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
053            final Exp exp = call.getArg(0);
054            final ExpCacheDescriptor cacheDescriptor =
055                    new ExpCacheDescriptor(exp, compiler);
056            return new GenericCalc(call) {
057                public Object evaluate(Evaluator evaluator) {
058                    return evaluator.getCachedResult(cacheDescriptor);
059                }
060    
061                public Calc[] getCalcs() {
062                    return new Calc[] {cacheDescriptor.getCalc()};
063                }
064    
065                public ResultStyle getResultStyle() {
066                    // cached lists are immutable
067                    if (type instanceof SetType) {
068                        return ResultStyle.LIST;
069                    } else {
070                        return ResultStyle.VALUE;
071                    }
072                }
073            };
074        }
075    
076        public static class CacheFunResolver extends ResolverBase {
077            CacheFunResolver() {
078                super(NAME, SIGNATURE, DESCRIPTION, SYNTAX);
079            }
080    
081            public FunDef resolve(
082                    Exp[] args, Validator validator, int[] conversionCount) {
083                if (args.length != 1) {
084                    return null;
085                }
086                final Exp exp = args[0];
087                final int category = exp.getCategory();
088                final Type type = exp.getType();
089                return new CacheFunDef(NAME, SIGNATURE, DESCRIPTION, SYNTAX,
090                        category, type);
091            }
092    
093            public boolean requiresExpression(int k) {
094                return false;
095            }
096        }
097    }
098    
099    // End CacheFunDef.java