001    /*
002    // $Id: //open/mondrian/src/main/mondrian/rolap/agg/ValueColumnPredicate.java#6 $
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) 2006-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.BitKey;
013    import mondrian.rolap.RolapStar;
014    import mondrian.rolap.StarPredicate;
015    import mondrian.rolap.StarColumnPredicate;
016    import mondrian.rolap.RolapUtil;
017    import mondrian.rolap.sql.SqlQuery;
018    
019    import java.util.Collection;
020    
021    /**
022     * A constraint which requires a column to have a particular value.
023     *
024     * @author jhyde
025     * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/ValueColumnPredicate.java#6 $
026     * @since Nov 2, 2006
027     */
028    public class ValueColumnPredicate
029        extends AbstractColumnPredicate
030        implements Comparable
031    {
032        private final Object value;
033    
034        /**
035         * Creates a column constraint.
036         *
037         * @param value Value to constraint the column to. (We require that it is
038         *   {@link Comparable} because we will sort the values in order to
039         *   generate deterministic SQL.)
040         */
041        public ValueColumnPredicate(
042            RolapStar.Column constrainedColumn,
043            Object value)
044        {
045            super(constrainedColumn);
046    //        assert constrainedColumn != null;
047            assert value != null;
048            assert ! (value instanceof StarColumnPredicate);
049            this.value = value;
050        }
051    
052        /**
053         * Returns the value which the column is compared to.
054         */
055        public Object getValue() {
056            return value;
057        }
058    
059        public String toString() {
060            return String.valueOf(value);
061        }
062    
063        public boolean equalConstraint(StarPredicate that) {
064            return that instanceof ValueColumnPredicate &&
065                getConstrainedColumnBitKey().equals(that.getConstrainedColumnBitKey()) &&
066                this.value.equals(((ValueColumnPredicate) that).value);
067        }
068    
069        public int compareTo(Object o) {
070            ValueColumnPredicate that = (ValueColumnPredicate) o;
071            int columnBitKeyComp =
072                getConstrainedColumnBitKey().compareTo(that.getConstrainedColumnBitKey());
073    
074            // First compare the column bitkeys.
075            if (columnBitKeyComp != 0) {
076                return columnBitKeyComp;
077            }
078    
079            if (this.value instanceof Comparable &&
080                that.value instanceof Comparable &&
081                this.value.getClass() == that.value.getClass()) {
082                return ((Comparable) this.value).compareTo(that.value);
083            } else {
084                String thisComp = String.valueOf(this.value);
085                String thatComp = String.valueOf(that.value);
086                return thisComp.compareTo(thatComp);
087            }
088        }
089    
090        public boolean equals(Object other) {
091            if (!(other instanceof ValueColumnPredicate)) {
092                return false;
093            }
094            final ValueColumnPredicate that = (ValueColumnPredicate) other;
095            int columnBitKeyComp =
096                getConstrainedColumnBitKey().compareTo(that.getConstrainedColumnBitKey());
097    
098            // First compare the column bitkeys.
099            if (columnBitKeyComp != 0) {
100                return false;
101            }
102    
103            if (value != null) {
104                return value.equals(that.getValue());
105            } else {
106                return null == that.getValue();
107            }
108        }
109    
110        public int hashCode() {
111            int hashCode = getConstrainedColumnBitKey().hashCode();
112    
113            if (value != null) {
114                hashCode = hashCode ^ value.hashCode();
115            }
116    
117            return hashCode;
118        }
119    
120        public void values(Collection<Object> collection) {
121            collection.add(value);
122        }
123    
124        public boolean evaluate(Object value) {
125            return this.value.equals(value);
126        }
127    
128        public void describe(StringBuilder buf) {
129            buf.append(value);
130        }
131    
132        public Overlap intersect(StarColumnPredicate predicate) {
133            throw new UnsupportedOperationException();
134        }
135    
136        public boolean mightIntersect(StarPredicate other) {
137            return ((StarColumnPredicate) other).evaluate(value);
138        }
139    
140        public StarColumnPredicate minus(StarPredicate predicate) {
141            assert predicate != null;
142            if (((StarColumnPredicate) predicate).evaluate(value)) {
143                return LiteralStarPredicate.FALSE;
144            } else {
145                return this;
146            }
147        }
148    
149        public StarColumnPredicate cloneWithColumn(RolapStar.Column column) {
150            return new ValueColumnPredicate(column, value);
151        }
152    
153        public void toSql(SqlQuery sqlQuery, StringBuilder buf) {
154            final RolapStar.Column column = getConstrainedColumn();
155            String expr = column.generateExprString(sqlQuery);
156            buf.append(expr);
157            Object key = getValue();
158            if (key == RolapUtil.sqlNullValue) {
159                buf.append(" is null");
160            } else {
161                buf.append(" = ");
162                sqlQuery.getDialect().quote(buf, key, column.getDatatype());
163            }
164        }
165    
166        public BitKey checkInList(BitKey inListLHSBitKey) {
167            // ValueColumn predicate by itself is not using IN list; when it is
168            // one of the children to an OR predicate, then using IN list
169            // is helpful. The later is checked by passing in a bitmap that
170            // represent the LHS or the IN list, i.e. the column that is
171            // constrained by the OR.
172            BitKey inListRHSBitKey = inListLHSBitKey.copy();
173    
174            if (!getConstrainedColumnBitKey().equals(inListLHSBitKey) ||
175                value == RolapUtil.sqlNullValue) {
176                inListRHSBitKey.clear();
177            }
178    
179            return inListRHSBitKey;
180        }
181    
182        public void toInListSql(SqlQuery sqlQuery, StringBuilder buf) {
183            sqlQuery.getDialect().quote(
184                buf, value, getConstrainedColumn().getDatatype());
185        }
186    }
187    
188    // End ValueColumnPredicate.java