add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / xml-query-parser / src / java / org / apache / lucene / xmlparser / builders / CachedFilterBuilder.java
1 /*
2  * Created on 25-Jan-2006
3  */
4 package org.apache.lucene.xmlparser.builders;
5
6 import java.util.Map.Entry;
7
8 import org.apache.lucene.search.CachingWrapperFilter;
9 import org.apache.lucene.search.Filter;
10 import org.apache.lucene.search.Query;
11 import org.apache.lucene.search.QueryWrapperFilter;
12 import org.apache.lucene.xmlparser.DOMUtils;
13 import org.apache.lucene.xmlparser.FilterBuilder;
14 import org.apache.lucene.xmlparser.FilterBuilderFactory;
15 import org.apache.lucene.xmlparser.ParserException;
16 import org.apache.lucene.xmlparser.QueryBuilder;
17 import org.apache.lucene.xmlparser.QueryBuilderFactory;
18 import org.w3c.dom.Element;
19 /**
20  * Licensed to the Apache Software Foundation (ASF) under one or more
21  * contributor license agreements.  See the NOTICE file distributed with
22  * this work for additional information regarding copyright ownership.
23  * The ASF licenses this file to You under the Apache License, Version 2.0
24  * (the "License"); you may not use this file except in compliance with
25  * the License.  You may obtain a copy of the License at
26  *
27  *     http://www.apache.org/licenses/LICENSE-2.0
28  *
29  * Unless required by applicable law or agreed to in writing, software
30  * distributed under the License is distributed on an "AS IS" BASIS,
31  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32  * See the License for the specific language governing permissions and
33  * limitations under the License.
34  */
35 /**
36  * Filters are cached in an LRU Cache keyed on the contained query or filter object. Using this will 
37  * speed up overall performance for repeated uses of the same expensive query/filter. The sorts of 
38  * queries/filters likely to benefit from caching need not necessarily be complex - e.g. simple 
39  * TermQuerys with a large DF (document frequency) can be expensive     on large indexes. 
40  * A good example of this might be a term query on a field with only 2 possible values - 
41  * "true" or "false". In a large index, querying or filtering on this field requires reading 
42  * millions     of document ids from disk which can more usefully be cached as a filter bitset.
43  * 
44  * For Queries/Filters to be cached and reused the object must implement hashcode and
45  * equals methods correctly so that duplicate queries/filters can be detected in the cache.
46  * 
47  * The CoreParser.maxNumCachedFilters property can be used to control the size of the LRU 
48  * Cache established during the construction of CoreParser instances.
49  *
50  */
51 public class CachedFilterBuilder implements FilterBuilder {
52
53         private QueryBuilderFactory queryFactory;
54         private FilterBuilderFactory filterFactory;
55         
56     private  LRUCache<Object,Filter> filterCache = null;
57
58         private int cacheSize;
59
60         public CachedFilterBuilder(QueryBuilderFactory queryFactory, 
61                         FilterBuilderFactory filterFactory,int cacheSize)
62         {
63                 this.queryFactory=queryFactory;
64                 this.filterFactory=filterFactory;
65                 this.cacheSize=cacheSize;
66         }
67
68         public synchronized Filter getFilter(Element e) throws ParserException
69         {
70
71                 Element childElement = DOMUtils.getFirstChildOrFail(e);
72
73                 if (filterCache == null)
74                 {
75                         filterCache = new LRUCache<Object,Filter>(cacheSize);
76                 }
77
78                 // Test to see if child Element is a query or filter that needs to be
79                 // cached
80                 QueryBuilder qb = queryFactory.getQueryBuilder(childElement.getNodeName());
81                 Object cacheKey = null;
82                 Query q = null;
83                 Filter f = null;
84                 if (qb != null)
85                 {
86                         q = qb.getQuery(childElement);
87                         cacheKey = q;
88                 } else
89                 {
90                         f = filterFactory.getFilter(childElement);
91                         cacheKey = f;
92                 }
93                 Filter cachedFilter = filterCache.get(cacheKey);
94                 if (cachedFilter != null)
95                 {
96                         return cachedFilter; // cache hit
97                 }
98                 
99                 //cache miss
100                 if (qb != null)
101                 {
102                         cachedFilter = new QueryWrapperFilter(q);
103                 } else
104                 {
105                         cachedFilter = new CachingWrapperFilter(f);
106                 }
107
108                 filterCache.put(cacheKey, cachedFilter);
109                 return cachedFilter;
110         }
111         
112         static class LRUCache<K,V> extends java.util.LinkedHashMap<K,V>
113         {
114             public LRUCache(int maxsize)
115             {
116                 super(maxsize * 4 / 3 + 1, 0.75f, true);
117                 this.maxsize = maxsize;
118             }
119
120             protected int maxsize;
121
122             @Override
123             protected boolean removeEldestEntry(Entry<K,V> eldest)
124             {
125                 return size() > maxsize;
126             }
127
128         }
129
130 }