001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.search;
017:
018: import org.apache.lucene.search.Query;
019: import org.apache.lucene.search.Sort;
020: import org.apache.lucene.search.SortField;
021:
022: import java.util.List;
023:
024: /** A hash key encapsulating a query, a list of filters, and a sort
025: * @author yonik
026: * @version $Id: QueryResultKey.java 533177 2007-04-27 17:50:15Z yonik $
027: */
028: public final class QueryResultKey {
029: final Query query;
030: final Sort sort;
031: final SortField[] sfields;
032: final List<Query> filters;
033: final int nc_flags; // non-comparable flags... ignored by hashCode and equals
034:
035: private final int hc; // cached hashCode
036:
037: private static SortField[] defaultSort = new SortField[0];
038:
039: public QueryResultKey(Query query, List<Query> filters, Sort sort,
040: int nc_flags) {
041: this .query = query;
042: this .sort = sort;
043: this .filters = filters;
044: this .nc_flags = nc_flags;
045:
046: int h = query.hashCode();
047:
048: if (filters != null)
049: h ^= filters.hashCode();
050:
051: sfields = (this .sort != null) ? this .sort.getSort()
052: : defaultSort;
053: for (SortField sf : sfields) {
054: // mix the bits so that sortFields are position dependent
055: // so that a,b won't hash to the same value as b,a
056: h ^= (h << 8) | (h >>> 25); // reversible hash
057:
058: if (sf.getField() != null)
059: h += sf.getField().hashCode();
060: h += sf.getType();
061: if (sf.getReverse())
062: h = ~h;
063: if (sf.getLocale() != null)
064: h += sf.getLocale().hashCode();
065: if (sf.getFactory() != null)
066: h += sf.getFactory().hashCode();
067: }
068:
069: hc = h;
070: }
071:
072: public int hashCode() {
073: return hc;
074: }
075:
076: public boolean equals(Object o) {
077: if (o == this )
078: return true;
079: if (!(o instanceof QueryResultKey))
080: return false;
081: QueryResultKey other = (QueryResultKey) o;
082:
083: // fast check of the whole hash code... most hash tables will only use
084: // some of the bits, so if this is a hash collision, it's still likely
085: // that the full cached hash code will be different.
086: if (this .hc != other.hc)
087: return false;
088:
089: // check for the thing most likely to be different (and the fastest things)
090: // first.
091: if (this .sfields.length != other.sfields.length)
092: return false;
093: if (!this .query.equals(other.query))
094: return false;
095: if (!isEqual(this .filters, other.filters))
096: return false;
097:
098: for (int i = 0; i < sfields.length; i++) {
099: SortField sf1 = this .sfields[i];
100: SortField sf2 = other.sfields[i];
101: if (sf1.getType() != sf2.getType())
102: return false;
103: if (sf1.getReverse() != sf2.getReverse())
104: return false;
105: if (!isEqual(sf1.getField(), sf2.getField()))
106: return false;
107: if (!isEqual(sf1.getLocale(), sf2.getLocale()))
108: return false;
109: if (!isEqual(sf1.getFactory(), sf2.getFactory()))
110: return false;
111: // NOTE: the factory must be identical!!! use singletons!
112: }
113:
114: return true;
115: }
116:
117: private static boolean isEqual(Object o1, Object o2) {
118: if (o1 == o2)
119: return true; // takes care of identity and null cases
120: if (o1 == null || o2 == null)
121: return false;
122: return o1.equals(o2);
123: }
124: }
|