001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/ListPredicate.java#7 $ 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-2008 Julian Hyde 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.StarPredicate; 013 import mondrian.rolap.RolapStar; 014 import mondrian.rolap.BitKey; 015 import mondrian.rolap.sql.SqlQuery; 016 import mondrian.olap.Util; 017 018 import java.util.HashMap; 019 import java.util.List; 020 import java.util.ArrayList; 021 022 /** 023 * Base class for {@link AndPredicate} and {@link OrPredicate}. 024 * 025 * @see mondrian.rolap.agg.ListColumnPredicate 026 * 027 * @author jhyde 028 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/ListPredicate.java#7 $ 029 */ 030 public abstract class ListPredicate implements StarPredicate { 031 protected final List<StarPredicate> children = 032 new ArrayList<StarPredicate>(); 033 034 /** 035 * Hash map of children predicates, keyed off of the hash code of each 036 * child. Each entry in the map is a list of predicates matching that 037 * hash code. 038 */ 039 private HashMap<Integer, List<StarPredicate>> childrenHashMap; 040 041 /** 042 * Pre-computed hash code for this list column predicate 043 */ 044 private int hashValue; 045 046 protected final List<RolapStar.Column> columns = 047 new ArrayList<RolapStar.Column>(); 048 049 protected BitKey columnBitKey; 050 051 protected ListPredicate(List<StarPredicate> predicateList) { 052 columnBitKey = null; 053 childrenHashMap = null; 054 hashValue = 0; 055 for (StarPredicate predicate : predicateList) { 056 if (columnBitKey == null) { 057 columnBitKey = 058 predicate.getConstrainedColumnBitKey().copy(); 059 } else { 060 columnBitKey = 061 columnBitKey.or(predicate.getConstrainedColumnBitKey()); 062 } 063 children.add(predicate); 064 for (RolapStar.Column column : 065 predicate.getConstrainedColumnList()) { 066 if (!columns.contains(column)) { 067 columns.add(column); 068 } 069 } 070 } 071 } 072 073 public List<RolapStar.Column> getConstrainedColumnList() { 074 return columns; 075 } 076 077 public BitKey getConstrainedColumnBitKey() { 078 return columnBitKey; 079 } 080 081 public List<StarPredicate> getChildren() { 082 return children; 083 } 084 085 public int hashCode() { 086 // Don't use the default list hashcode because we want a hash code 087 // that's not order dependent 088 if (hashValue == 0) { 089 hashValue = 37; 090 for (StarPredicate child : children) { 091 int childHashCode = child.hashCode(); 092 if (childHashCode != 0) { 093 hashValue *= childHashCode; 094 } 095 } 096 hashValue ^= children.size(); 097 } 098 return hashValue; 099 } 100 101 public boolean equalConstraint(StarPredicate that) { 102 boolean isEqual = 103 that instanceof ListPredicate && 104 getConstrainedColumnBitKey().equals( 105 that.getConstrainedColumnBitKey()); 106 107 if (isEqual) { 108 ListPredicate thatPred = (ListPredicate) that; 109 if (getOp() != thatPred.getOp() || 110 getChildren().size() != thatPred.getChildren().size()) { 111 isEqual = false; 112 } 113 114 if (isEqual) { 115 // Create a hash map of the children predicates, if not 116 // already done 117 if (childrenHashMap == null) { 118 childrenHashMap = 119 new HashMap<Integer, List<StarPredicate>>(); 120 for (StarPredicate thisChild : getChildren()) { 121 Integer key = new Integer(thisChild.hashCode()); 122 List<StarPredicate> predList = childrenHashMap.get(key); 123 if (predList == null) { 124 predList = new ArrayList<StarPredicate>(); 125 } 126 predList.add(thisChild); 127 childrenHashMap.put(key, predList); 128 } 129 } 130 131 // Loop through thatPred's children predicates. There needs 132 // to be a matching entry in the hash map for each child 133 // predicate. 134 for (StarPredicate thatChild : thatPred.getChildren()) { 135 List<StarPredicate> predList = 136 childrenHashMap.get(thatChild.hashCode()); 137 if (predList == null) { 138 isEqual = false; 139 break; 140 } 141 boolean foundMatch = false; 142 for (StarPredicate pred : predList) { 143 if (thatChild.equalConstraint(pred)) { 144 foundMatch = true; 145 break; 146 } 147 } 148 if (!foundMatch) { 149 isEqual = false; 150 break; 151 } 152 } 153 } 154 } 155 156 return isEqual; 157 158 } 159 160 public StarPredicate minus(StarPredicate predicate) { 161 throw Util.needToImplement(this); 162 } 163 164 public void toSql(SqlQuery sqlQuery, StringBuilder buf) { 165 if (children.size() == 1) { 166 children.get(0).toSql(sqlQuery, buf); 167 } else { 168 int k = 0; 169 buf.append("("); 170 for (StarPredicate child : children) { 171 if (k++ > 0) { 172 buf.append(" ").append(getOp()).append(" "); 173 } 174 child.toSql(sqlQuery, buf); 175 } 176 buf.append(")"); 177 } 178 } 179 180 protected abstract String getOp(); 181 182 public void describe(StringBuilder buf) { 183 buf.append(getOp()).append("("); 184 int k = 0; 185 for (StarPredicate child : children) { 186 if (k++ > 0) { 187 buf.append(", "); 188 } 189 buf.append(child); 190 } 191 buf.append(')'); 192 } 193 194 195 public String toString() { 196 final StringBuilder buf = new StringBuilder(); 197 describe(buf); 198 return buf.toString(); 199 } 200 } 201 202 // End ListPredicate.java