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-2012 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.rolap;
011
012import mondrian.olap.*;
013import mondrian.resource.MondrianResource;
014import mondrian.spi.CellFormatter;
015import mondrian.spi.Dialect;
016
017import java.util.*;
018
019/**
020 * Measure which is computed from a SQL column (or expression) and which is
021 * defined in a non-virtual cube.
022 *
023 * @see RolapVirtualCubeMeasure
024 *
025 * @author jhyde
026 * @since 24 August, 2006
027 */
028public class RolapBaseCubeMeasure
029    extends RolapMemberBase
030    implements RolapStoredMeasure
031{
032    static enum DataType {
033        Integer,
034        Numeric,
035        String
036    }
037
038    /**
039     * For SQL generator. Column which holds the value of the measure.
040     */
041    private final MondrianDef.Expression expression;
042
043    /**
044     * For SQL generator. Has values "SUM", "COUNT", etc.
045     */
046    private final RolapAggregator aggregator;
047
048    private final RolapCube cube;
049    private final Map<String, Annotation> annotationMap;
050
051    /**
052     * Holds the {@link mondrian.rolap.RolapStar.Measure} from which this
053     * member is computed. Untyped, because another implementation might store
054     * it somewhere else.
055     */
056    private Object starMeasure;
057
058    private RolapResult.ValueFormatter formatter;
059
060    /**
061     * Creates a RolapBaseCubeMeasure.
062     *
063     * @param cube Cube
064     * @param parentMember Parent member
065     * @param level Level this member belongs to
066     * @param name Name of this member
067     * @param caption Caption
068     * @param description Description
069     * @param formatString Format string
070     * @param expression Expression
071     * @param aggregatorName Aggregator
072     * @param datatype Data type
073     * @param annotationMap Annotations
074     */
075    RolapBaseCubeMeasure(
076        RolapCube cube,
077        RolapMember parentMember,
078        RolapLevel level,
079        String name,
080        String caption,
081        String description,
082        String formatString,
083        MondrianDef.Expression expression,
084        String aggregatorName,
085        String datatype,
086        Map<String, Annotation> annotationMap)
087    {
088        super(parentMember, level, name, null, MemberType.MEASURE);
089        assert annotationMap != null;
090        this.cube = cube;
091        this.annotationMap = annotationMap;
092        this.caption = caption;
093        this.expression = expression;
094        if (description != null) {
095            setProperty(
096                Property.DESCRIPTION.name,
097                description);
098        }
099        if (formatString == null) {
100            formatString = "";
101        } else {
102            setProperty(
103                Property.FORMAT_STRING.name,
104                formatString);
105        }
106        setProperty(
107            Property.FORMAT_EXP_PARSED.name,
108            Literal.createString(formatString));
109        setProperty(
110            Property.FORMAT_EXP.name,
111            formatString);
112
113        // Validate aggregator.
114        this.aggregator =
115            RolapAggregator.enumeration.getValue(aggregatorName, false);
116        if (this.aggregator == null) {
117            StringBuilder buf = new StringBuilder();
118            for (String aggName : RolapAggregator.enumeration.getNames()) {
119                if (buf.length() > 0) {
120                    buf.append(", ");
121                }
122                buf.append('\'');
123                buf.append(aggName);
124                buf.append('\'');
125            }
126            throw MondrianResource.instance().UnknownAggregator.ex(
127                aggregatorName,
128                buf.toString());
129        }
130
131        setProperty(Property.AGGREGATION_TYPE.name, aggregator);
132        if (datatype == null) {
133            if (aggregator == RolapAggregator.Count
134                || aggregator == RolapAggregator.DistinctCount)
135            {
136                datatype = "Integer";
137            } else {
138                datatype = "Numeric";
139            }
140        }
141        if (RolapBaseCubeMeasure.DataType.valueOf(datatype) == null) {
142            throw MondrianResource.instance().CastInvalidType.ex(datatype);
143        }
144        setProperty(Property.DATATYPE.name, datatype);
145    }
146
147    public MondrianDef.Expression getMondrianDefExpression() {
148        return expression;
149    }
150
151    public RolapAggregator getAggregator() {
152        return aggregator;
153    }
154
155    public RolapCube getCube() {
156        return cube;
157    }
158
159    public RolapResult.ValueFormatter getFormatter() {
160        return formatter;
161    }
162
163    public void setFormatter(CellFormatter cellFormatter) {
164        this.formatter =
165            new RolapResult.CellFormatterValueFormatter(cellFormatter);
166    }
167
168    public Object getStarMeasure() {
169        return starMeasure;
170    }
171
172    void setStarMeasure(Object starMeasure) {
173        this.starMeasure = starMeasure;
174    }
175
176    @Override
177    public Map<String, Annotation> getAnnotationMap() {
178        return annotationMap;
179    }
180
181    public Dialect.Datatype getDatatype() {
182        Object datatype = getPropertyValue(Property.DATATYPE.name);
183        try {
184            return Dialect.Datatype.valueOf((String) datatype);
185        } catch (ClassCastException e) {
186            return Dialect.Datatype.String;
187        } catch (IllegalArgumentException e) {
188            return Dialect.Datatype.String;
189        }
190    }
191}
192
193// End RolapBaseCubeMeasure.java