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 008// All Rights Reserved. 009*/ 010package mondrian.calc.impl; 011 012import mondrian.calc.*; 013import mondrian.olap.*; 014import mondrian.olap.fun.FunUtil; 015 016import java.util.Date; 017 018/** 019 * Adapter which computes a scalar or tuple expression and converts it to any 020 * required type. 021 * 022 * @see mondrian.calc.impl.GenericIterCalc 023 * 024 * @author jhyde 025 * @since Sep 26, 2005 026 */ 027public abstract class GenericCalc 028 extends AbstractCalc 029 implements TupleCalc, 030 StringCalc, IntegerCalc, DoubleCalc, BooleanCalc, DateTimeCalc, 031 VoidCalc, MemberCalc, LevelCalc, HierarchyCalc, DimensionCalc 032{ 033 /** 034 * Creates a GenericCalc without specifying child calculated expressions. 035 * 036 * <p>Subclass should override {@link #getCalcs()}. 037 * 038 * @param exp Source expression 039 */ 040 protected GenericCalc(Exp exp) { 041 super(exp, null); 042 } 043 044 /** 045 * Creates an GenericCalc. 046 * 047 * @param exp Source expression 048 * @param calcs Child compiled expressions 049 */ 050 protected GenericCalc(Exp exp, Calc[] calcs) { 051 super(exp, calcs); 052 } 053 054 public Member[] evaluateTuple(Evaluator evaluator) { 055 return (Member[]) evaluate(evaluator); 056 } 057 058 private String msg(TypeEnum expectedType, Object o) { 059 final TypeEnum actualType = actualType(o); 060 return "Expected value of type " + expectedType + "; got value '" + o 061 + "' (" + (actualType == null ? o.getClass() : actualType) + ")"; 062 } 063 064 private static TypeEnum actualType(Object o) { 065 if (o == null) { 066 return TypeEnum.NULL; 067 } else if (o instanceof String) { 068 return TypeEnum.STRING; 069 } else if (o instanceof Boolean) { 070 return TypeEnum.BOOLEAN; 071 } else if (o instanceof Number) { 072 return TypeEnum.NUMERIC; 073 } else if (o instanceof Date) { 074 return TypeEnum.DATETIME; 075 } else if (o instanceof Member) { 076 return TypeEnum.MEMBER; 077 } else if (o instanceof Level) { 078 return TypeEnum.LEVEL; 079 } else if (o instanceof Hierarchy) { 080 return TypeEnum.HIERARCHY; 081 } else if (o instanceof Dimension) { 082 return TypeEnum.DIMENSION; 083 } else { 084 return null; 085 } 086 } 087 088 public String evaluateString(Evaluator evaluator) { 089 final Object o = evaluate(evaluator); 090 try { 091 return (String) o; 092 } catch (ClassCastException e) { 093 throw evaluator.newEvalException(null, msg(TypeEnum.STRING, o)); 094 } 095 } 096 097 public int evaluateInteger(Evaluator evaluator) { 098 Object o = evaluate(evaluator); 099 try { 100 final Number number = (Number) o; 101 return number == null 102 ? FunUtil.IntegerNull 103 : number.intValue(); 104 } catch (ClassCastException e) { 105 throw evaluator.newEvalException(null, msg(TypeEnum.NUMERIC, o)); 106 } 107 } 108 109 public double evaluateDouble(Evaluator evaluator) { 110 final Object o = evaluate(evaluator); 111 try { 112 final Number number = (Number) o; 113 return numberToDouble(number); 114 } catch (ClassCastException e) { 115 throw evaluator.newEvalException(null, msg(TypeEnum.NUMERIC, o)); 116 } 117 } 118 119 public static double numberToDouble(Number number) { 120 return number == null 121 ? FunUtil.DoubleNull 122 : number.doubleValue(); 123 } 124 125 public boolean evaluateBoolean(Evaluator evaluator) { 126 final Object o = evaluate(evaluator); 127 try { 128 return (Boolean) o; 129 } catch (ClassCastException e) { 130 throw evaluator.newEvalException(null, msg(TypeEnum.BOOLEAN, o)); 131 } 132 } 133 134 public Date evaluateDateTime(Evaluator evaluator) { 135 final Object o = evaluate(evaluator); 136 try { 137 return (Date) o; 138 } catch (ClassCastException e) { 139 throw evaluator.newEvalException(null, msg(TypeEnum.DATETIME, o)); 140 } 141 } 142 143 public void evaluateVoid(Evaluator evaluator) { 144 final Object result = evaluate(evaluator); 145 assert result == null; 146 } 147 148 public Member evaluateMember(Evaluator evaluator) { 149 final Object o = evaluate(evaluator); 150 try { 151 return (Member) o; 152 } catch (ClassCastException e) { 153 throw evaluator.newEvalException(null, msg(TypeEnum.MEMBER, o)); 154 } 155 } 156 157 public Level evaluateLevel(Evaluator evaluator) { 158 final Object o = evaluate(evaluator); 159 try { 160 return (Level) o; 161 } catch (ClassCastException e) { 162 throw evaluator.newEvalException(null, msg(TypeEnum.LEVEL, o)); 163 } 164 } 165 166 public Hierarchy evaluateHierarchy(Evaluator evaluator) { 167 final Object o = evaluate(evaluator); 168 try { 169 return (Hierarchy) o; 170 } catch (ClassCastException e) { 171 throw evaluator.newEvalException(null, msg(TypeEnum.HIERARCHY, o)); 172 } 173 } 174 175 public Dimension evaluateDimension(Evaluator evaluator) { 176 final Object o = evaluate(evaluator); 177 try { 178 return (Dimension) o; 179 } catch (ClassCastException e) { 180 throw evaluator.newEvalException(null, msg(TypeEnum.DIMENSION, o)); 181 } 182 } 183 184 private enum TypeEnum { 185 NULL, 186 BOOLEAN, STRING, NUMERIC, DATETIME, 187 MEMBER, LEVEL, HIERARCHY, DIMENSION 188 } 189} 190 191// End GenericCalc.java