001    /*
002    // $Id: //open/mondrian/src/main/mondrian/calc/impl/BetterExpCompiler.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) 2006-2007 Julian Hyde
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.calc.impl;
011    
012    import mondrian.olap.*;
013    import mondrian.olap.type.*;
014    import mondrian.calc.*;
015    
016    import java.util.List;
017    import java.util.ArrayList;
018    
019    /**
020     * Enhanced expression compiler. It can generate code to convert between
021     * scalar types.
022     *
023     * @author jhyde
024     * @version $Id: //open/mondrian/src/main/mondrian/calc/impl/BetterExpCompiler.java#9 $
025     * @since Sep 29, 2005
026     */
027    public class BetterExpCompiler extends AbstractExpCompiler {
028        public BetterExpCompiler(Evaluator evaluator, Validator validator) {
029            super(evaluator, validator);
030        }
031    
032        public BetterExpCompiler(
033            Evaluator evaluator,
034            Validator validator,
035            List<ResultStyle> resultStyles)
036        {
037            super(evaluator, validator, resultStyles);
038        }
039    
040        public DoubleCalc compileDouble(Exp exp) {
041            final Calc calc = compileScalar(exp, false);
042            if (calc instanceof DoubleCalc) {
043                return (DoubleCalc) calc;
044            } else if (calc instanceof IntegerCalc) {
045                final IntegerCalc integerCalc = (IntegerCalc) calc;
046                return new AbstractDoubleCalc(exp, new Calc[] {integerCalc}) {
047                    public double evaluateDouble(Evaluator evaluator) {
048                        final int result = integerCalc.evaluateInteger(evaluator);
049                        return (double) result;
050                    }
051                };
052            } else {
053                throw Util.newInternal("cannot cast " + exp);
054            }
055        }
056    
057        public TupleCalc compileTuple(Exp exp) {
058            final Calc calc = compile(exp);
059            final Type type = exp.getType();
060            if (type instanceof TupleType) {
061                assert calc instanceof TupleCalc;
062                return (TupleCalc) calc;
063            } else if (type instanceof MemberType) {
064                assert calc instanceof MemberCalc;
065                final MemberCalc memberCalc = (MemberCalc) calc;
066                return new AbstractTupleCalc(exp, new Calc[] {memberCalc}) {
067                    public Member[] evaluateTuple(Evaluator evaluator) {
068                        return new Member[] {memberCalc.evaluateMember(evaluator)};
069                    }
070                };
071            } else {
072                throw Util.newInternal("cannot cast " + exp);
073            }
074        }
075    
076        public ListCalc compileList(Exp exp, boolean mutable) {
077            final ListCalc listCalc = super.compileList(exp, mutable);
078            if (mutable && listCalc.getResultStyle() == ResultStyle.LIST) {
079                // Wrap the expression in an expression which creates a mutable
080                // copy.
081                return new CopyListCalc(listCalc);
082            }
083            return listCalc;
084        }
085    
086        private static class CopyListCalc extends AbstractListCalc {
087            private final ListCalc listCalc;
088    
089            public CopyListCalc(ListCalc listCalc) {
090                super(new DummyExp(listCalc.getType()), new Calc[]{listCalc});
091                this.listCalc = listCalc;
092            }
093    
094            public List evaluateList(Evaluator evaluator) {
095                List list = listCalc.evaluateList(evaluator);
096                return new ArrayList(list);
097            }
098        }
099    }
100    
101    // End BetterExpCompiler.java