001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/GroupingSetsList.java#1 $ 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) 2007-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.rolap.agg; 011 012 import mondrian.rolap.RolapStar; 013 import mondrian.rolap.BitKey; 014 015 import java.util.*; 016 017 /** 018 * Class for using GROUP BY GROUPING SETS sql query. 019 * 020 * <p>For example, suppose we have the 3 grouping sets (a, b, c), (a, b) and 021 * (b, c).<ul> 022 * <li>detailed grouping set -> (a, b, c) 023 * <li>rolled-up grouping sets -> (a, b), (b, c) 024 * <li>rollup columns -> c, a (c for (a, b) and a for (b, c)) 025 * <li>rollup columns bitkey -><br/> 026 * (a, b, c) grouping set represented as 0, 0, 0<br/> 027 * (a, b) grouping set represented as 0, 0, 1<br/> 028 * (b, c) grouping set represented as 1, 0, 0 029 * </ul> 030 * 031 * @author Thiyagu 032 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/GroupingSetsList.java#1 $ 033 * @since 24 May 2007 034 */ 035 class GroupingSetsList { 036 037 private final List<RolapStar.Column> rollupColumns; 038 039 private final List<RolapStar.Column[]> groupingSetsColumns; 040 private final boolean useGroupingSet; 041 042 private final List<BitKey> rollupColumnsBitKeyList = 043 new ArrayList<BitKey>(); 044 045 /** 046 * Maps column index to grouping function index. 047 */ 048 private final Map<Integer, Integer> columnIndexToGroupingIndexMap = 049 new HashMap<Integer, Integer>(); 050 051 private final List<GroupingSet> groupingSets; 052 053 /** 054 * Creates a GroupingSetsList. 055 * 056 * <p>First element of the groupingSets list should be the detailed 057 * grouping set (default grouping set), followed by grouping sets which can 058 * be rolled-up. 059 * 060 * @param groupingSets List of groups of columns 061 */ 062 public GroupingSetsList(List<GroupingSet> groupingSets) { 063 this.groupingSets = groupingSets; 064 this.useGroupingSet = groupingSets.size() > 1; 065 if (useGroupingSet) { 066 this.groupingSetsColumns = getGroupingColumnsList(groupingSets); 067 this.rollupColumns = findRollupColumns(); 068 loadRollupIndex(); 069 loadGroupingColumnBitKeys(); 070 } else { 071 this.groupingSetsColumns = new ArrayList<RolapStar.Column[]>(); 072 this.rollupColumns = new ArrayList<RolapStar.Column>(); 073 } 074 } 075 076 List<RolapStar.Column[]> getGroupingColumnsList( 077 List<GroupingSet> groupingSets) 078 { 079 List<RolapStar.Column[]> groupingColumns = 080 new ArrayList<RolapStar.Column[]>(); 081 for (GroupingSet aggBatchDetail : groupingSets) { 082 groupingColumns.add(aggBatchDetail.getSegments()[0] 083 .aggregation.getColumns()); 084 085 } 086 return groupingColumns; 087 } 088 089 public List<RolapStar.Column> getRollupColumns() { 090 return rollupColumns; 091 } 092 093 public List<RolapStar.Column[]> getGroupingSetsColumns() { 094 return groupingSetsColumns; 095 } 096 097 public List<BitKey> getRollupColumnsBitKeyList() { 098 return rollupColumnsBitKeyList; 099 } 100 101 public BitKey getDetailedColumnsBitKey() { 102 return rollupColumnsBitKeyList.get(0); 103 } 104 105 private void loadGroupingColumnBitKeys() { 106 int bitKeyLength = getDefaultColumns().length; 107 for (RolapStar.Column[] groupingSetColumns : groupingSetsColumns) { 108 BitKey groupingColumnsBitKey = 109 BitKey.Factory.makeBitKey(bitKeyLength); 110 Set<RolapStar.Column> columns = 111 convertToSet(groupingSetColumns); 112 int bitPosition = 0; 113 for (RolapStar.Column rollupColumn : rollupColumns) { 114 if (!columns.contains(rollupColumn)) { 115 groupingColumnsBitKey.set(bitPosition); 116 } 117 bitPosition++; 118 } 119 rollupColumnsBitKeyList.add(groupingColumnsBitKey); 120 } 121 } 122 123 private void loadRollupIndex() { 124 RolapStar.Column[] detailedColumns = getDefaultColumns(); 125 for (int columnIndex = 0; columnIndex < detailedColumns.length; 126 columnIndex++) { 127 int rollupIndex = 128 rollupColumns.indexOf(detailedColumns[columnIndex]); 129 columnIndexToGroupingIndexMap.put(columnIndex, rollupIndex); 130 } 131 } 132 133 private List<RolapStar.Column> findRollupColumns() { 134 Set<RolapStar.Column> rollupSet = new TreeSet<RolapStar.Column>( 135 RolapStar.ColumnComparator.instance); 136 for (RolapStar.Column[] groupingSetColumn : groupingSetsColumns) { 137 Set<RolapStar.Column> summaryColumns = 138 convertToSet(groupingSetColumn); 139 for (RolapStar.Column column : getDefaultColumns()) { 140 if (!summaryColumns.contains(column)) { 141 rollupSet.add(column); 142 } 143 } 144 } 145 return new ArrayList<RolapStar.Column>(rollupSet); 146 } 147 148 private Set<RolapStar.Column> convertToSet(RolapStar.Column[] columns) { 149 HashSet<RolapStar.Column> columnSet = new HashSet<RolapStar.Column>(); 150 for (RolapStar.Column column : columns) { 151 columnSet.add(column); 152 } 153 return columnSet; 154 } 155 156 public boolean useGroupingSets() { 157 return useGroupingSet; 158 } 159 160 public int findGroupingFunctionIndex(int columnIndex) { 161 return columnIndexToGroupingIndexMap.get(columnIndex); 162 } 163 164 public Aggregation.Axis[] getDefaultAxes() { 165 return getDefaultGroupingSet().getAxes(); 166 } 167 168 protected GroupingSet getDefaultGroupingSet() { 169 return groupingSets.get(0); 170 } 171 172 public RolapStar.Column[] getDefaultColumns() { 173 return getDefaultGroupingSet().getSegments()[0].aggregation 174 .getColumns(); 175 } 176 177 public Segment[] getDefaultSegments() { 178 return getDefaultGroupingSet().getSegments(); 179 } 180 181 public BitKey getDefaultLevelBitKey() { 182 return getDefaultGroupingSet().getLevelBitKey(); 183 } 184 185 public BitKey getDefaultMeasureBitKey() { 186 return getDefaultGroupingSet().getMeasureBitKey(); 187 } 188 189 public RolapStar getStar() { 190 return getDefaultSegments()[0].aggregation.getStar(); 191 } 192 193 public List<GroupingSet> getGroupingSets() { 194 return groupingSets; 195 } 196 197 public List<GroupingSet> getRollupGroupingSets() { 198 ArrayList<GroupingSet> rollupGroupingSets = 199 new ArrayList<GroupingSet>(groupingSets); 200 rollupGroupingSets.remove(0); 201 return rollupGroupingSets; 202 } 203 } 204 205 // End GroupingSetsList.java