001    /*
002    // $Id: //open/mondrian/src/main/mondrian/rolap/agg/SegmentArrayQuerySpec.java#19 $
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-2008 Julian Hyde and others
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    
011    package mondrian.rolap.agg;
012    
013    import mondrian.rolap.RolapStar;
014    import mondrian.rolap.StarColumnPredicate;
015    import mondrian.rolap.StarPredicate;
016    import mondrian.rolap.sql.SqlQuery;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    
021    /**
022     * Provides the information necessary to generate a SQL statement to
023     * retrieve a list of segments.
024     *
025     * @author jhyde
026     * @author Richard M. Emberson
027     * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/SegmentArrayQuerySpec.java#19 $
028     */
029    class SegmentArrayQuerySpec extends AbstractQuerySpec {
030        private final Segment[] segments;
031        private final GroupingSetsList groupingSetsList;
032    
033        /*
034         * Compound member predicates.
035         * Each list constrains one dimension.
036         */
037        private final List<StarPredicate> compoundPredicateList;
038    
039        /**
040         * Creates a SegmentArrayQuerySpec.
041         *
042         * @param groupingSetsList Collection of grouping sets
043         * @param compoundPredicateList list of predicates representing the
044         * compound member constraints
045         */
046        SegmentArrayQuerySpec(
047            GroupingSetsList groupingSetsList,
048            List<StarPredicate> compoundPredicateList)
049        {
050            super(groupingSetsList.getStar(), false);
051            this.segments = groupingSetsList.getDefaultSegments();
052            this.groupingSetsList = groupingSetsList;
053            this.compoundPredicateList = compoundPredicateList;
054            assert isValid(true);
055        }
056    
057        /**
058         * Returns whether this query specification is valid, or throws if invalid
059         * and <code>fail</code> is true.
060         *
061         * @param fail Whether to throw if invalid
062         * @return Whether this query specification is valid
063         */
064        private boolean isValid(boolean fail) {
065            assert segments.length > 0;
066            for (Segment segment : segments) {
067                if (segment.aggregation != segments[0].aggregation) {
068                    assert!fail;
069                    return false;
070                }
071                int n = segment.axes.length;
072                if (n != segments[0].axes.length) {
073                    assert!fail;
074                    return false;
075                }
076                for (int j = 0; j < segment.axes.length; j++) {
077                    // We only require that the two arrays have the same
078                    // contents, we but happen to know they are the same array,
079                    // because we constructed them at the same time.
080                    if (segment.axes[j].getPredicate() !=
081                        segments[0].axes[j].getPredicate()) {
082                        assert!fail;
083                        return false;
084                    }
085                }
086            }
087            return true;
088        }
089    
090        public int getMeasureCount() {
091            return segments.length;
092        }
093    
094        public RolapStar.Measure getMeasure(final int i) {
095            return segments[i].measure;
096        }
097    
098        public String getMeasureAlias(final int i) {
099            return "m" + Integer.toString(i);
100        }
101    
102        public RolapStar.Column[] getColumns() {
103            return segments[0].aggregation.getColumns();
104        }
105    
106        /**
107         * SqlQuery relies on "c" and index. All this should go into SqlQuery!
108         *
109         * @see mondrian.rolap.sql.SqlQuery#addOrderBy
110         */
111        public String getColumnAlias(final int i) {
112            return "c" + Integer.toString(i);
113        }
114    
115        public StarColumnPredicate getColumnPredicate(final int i) {
116            return segments[0].axes[i].getPredicate();
117        }
118    
119        protected List<StarPredicate> getPredicateList() {
120            if (compoundPredicateList == null) {
121                return super.getPredicateList();
122            } else {
123                return compoundPredicateList;
124            }
125        }
126    
127        protected void addGroupingFunction(SqlQuery sqlQuery) {
128            List<RolapStar.Column> list = groupingSetsList.getRollupColumns();
129            for (RolapStar.Column column : list) {
130                sqlQuery.addGroupingFunction(column.generateExprString(sqlQuery));
131            }
132        }
133    
134        protected void addGroupingSets(SqlQuery sqlQuery) {
135            List<RolapStar.Column[]> groupingSetsColumns =
136                groupingSetsList.getGroupingSetsColumns();
137            for (RolapStar.Column[] groupingSetsColumn : groupingSetsColumns) {
138                ArrayList<String> groupingColumnsExpr = new ArrayList<String>();
139                for (RolapStar.Column aColumn : groupingSetsColumn) {
140                    groupingColumnsExpr.add(aColumn.generateExprString(sqlQuery));
141                }
142                sqlQuery.addGroupingSet(groupingColumnsExpr);
143            }
144        }
145    
146        protected boolean isAggregate() {
147            return true;
148        }
149    }
150    
151    // End SegmentArrayQuerySpec.java