001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/AggregationKey.java#3 $ 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 package mondrian.rolap.agg; 011 012 import java.util.ArrayList; 013 import java.util.List; 014 import java.util.Map; 015 016 import mondrian.rolap.BitKey; 017 import mondrian.rolap.RolapStar; 018 import mondrian.rolap.StarPredicate; 019 020 /** 021 * This class defines the column context that an Aggregation is computed for. 022 * Column context has two components: 023 * -- the column constraints which define the dimentionality of an 024 * Aggregation 025 * -- an orthogonal context for which the measures are defined. This context 026 * is sometimes referred to as the compound member predicates, and usually of 027 * the shape: 028 * OR(AND(column predicates)) 029 * Any column is only used in either column context or compound context, not 030 * both. 031 * @author Rushan Chen 032 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/AggregationKey.java#3 $ 033 */ 034 public class AggregationKey 035 { 036 /** 037 * This is needed because for a Virtual Cube: two CellRequests 038 * could have the same BitKey but have different underlying 039 * base cubes. Without this, one get the result in the 040 * SegmentArrayQuerySpec addMeasure Util.assertTrue being 041 * triggered (which is what happened). 042 */ 043 private final RolapStar star; 044 045 private final BitKey constrainedColumnsBitKey; 046 047 /* 048 * This map must be deternimistic; otherwise different runs generate SQL 049 * statements in different orders. 050 * 051 * TODO: change this to SortedMap to speed up comparison. 052 */ 053 private final Map<BitKey, StarPredicate> compoundPredicateMap; 054 055 public AggregationKey(CellRequest request) { 056 this.constrainedColumnsBitKey = request.getConstrainedColumnsBitKey(); 057 this.star = request.getMeasure().getStar(); 058 compoundPredicateMap = request.getCompoundPredicateMap(); 059 } 060 061 public int hashCode() { 062 int retCode = 063 constrainedColumnsBitKey.hashCode() ^ star.hashCode(); 064 if (compoundPredicateMap != null) { 065 for (BitKey bitKey : compoundPredicateMap.keySet()) { 066 retCode ^= bitKey.hashCode(); 067 } 068 } 069 return retCode; 070 } 071 072 public boolean hasSameCompoundPredicate(AggregationKey otherKey) { 073 boolean isEqual = false; 074 if (compoundPredicateMap.size() == 075 otherKey.compoundPredicateMap.size()) { 076 isEqual = true; 077 for (BitKey bitKey : compoundPredicateMap.keySet()) { 078 StarPredicate thisPred = 079 compoundPredicateMap.get(bitKey); 080 StarPredicate otherPred = 081 otherKey.compoundPredicateMap.get(bitKey); 082 if (thisPred == null || otherPred == null || 083 !thisPred.equalConstraint(otherPred)) { 084 isEqual = false; 085 break; 086 } 087 } 088 } 089 return isEqual; 090 } 091 092 public boolean equals(Object other) { 093 if (other instanceof AggregationKey) { 094 AggregationKey otherKey = (AggregationKey) other; 095 if (constrainedColumnsBitKey.equals(otherKey.constrainedColumnsBitKey) && 096 star.equals(otherKey.star) && 097 hasSameCompoundPredicate(otherKey)) { 098 return true; 099 } 100 } 101 return false; 102 } 103 104 public String toString() { 105 return 106 star.getFactTable().getTableName() + " " + 107 constrainedColumnsBitKey.toString() + "\n" + 108 compoundPredicateMap.toString(); 109 } 110 111 public BitKey getConstrainedColumnsBitKey() { 112 return constrainedColumnsBitKey; 113 } 114 115 public RolapStar getStar() { 116 return star; 117 } 118 119 /** 120 * Get the set of compound predicates 121 * @return list of predicates 122 */ 123 public List<StarPredicate> getCompoundPredicateList() { 124 return (new ArrayList<StarPredicate>(compoundPredicateMap.values())); 125 } 126 127 } 128 129 // End AggregationKey.java