Clover coverage report -
Coverage timestamp: Sun Nov 1 2009 23:08:24 UTC
file stats: LOC: 234   Methods: 16
NCLOC: 158   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
TextQueryResolver.java 77.3% 78.1% 68.8% 76.5%
coverage coverage
 1    /*
 2    * Licensed to the Apache Software Foundation (ASF) under one or more
 3    * contributor license agreements. See the NOTICE file distributed with
 4    * this work for additional information regarding copyright ownership.
 5    * The ASF licenses this file to You under the Apache License, Version 2.0
 6    * (the "License"); you may not use this file except in compliance with
 7    * the License. You may obtain a copy of the License at
 8    *
 9    * http://www.apache.org/licenses/LICENSE-2.0
 10    *
 11    * Unless required by applicable law or agreed to in writing, software
 12    * distributed under the License is distributed on an "AS IS" BASIS,
 13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    * See the License for the specific language governing permissions and
 15    * limitations under the License.
 16    *
 17    * $Id: TextQueryResolver.java 577512 2007-09-20 02:27:54Z natalia $
 18    */
 19   
 20    package org.apache.xindice.core.query;
 21   
 22    import java.util.HashSet;
 23   
 24    import org.apache.commons.logging.Log;
 25    import org.apache.commons.logging.LogFactory;
 26   
 27    import org.apache.xindice.core.Collection;
 28    import org.apache.xindice.core.data.Key;
 29    import org.apache.xindice.core.data.NodeSet;
 30    import org.apache.xindice.core.data.Entry;
 31    import org.apache.xindice.core.DBException;
 32    import org.apache.xindice.core.FaultCodes;
 33    import org.apache.xindice.core.indexer.LuceneIndexer;
 34    import org.apache.xindice.core.indexer.Indexer;
 35    import org.apache.xindice.core.indexer.IndexMatch;
 36    import org.apache.xindice.util.SimpleConfigurable;
 37    import org.apache.xindice.util.XindiceRuntimeException;
 38    import org.apache.xindice.xml.dom.DBDocument;
 39    import org.apache.xindice.xml.NamespaceMap;
 40    import org.apache.lucene.queryParser.QueryParser;
 41    import org.apache.lucene.queryParser.ParseException;
 42    import org.apache.lucene.analysis.Analyzer;
 43   
 44    import org.w3c.dom.Node;
 45   
 46    /**
 47    * Query resolver for full text queries. Requires existing full text index
 48    * to work.
 49    *
 50    * @see org.apache.xindice.core.indexer.LuceneIndexer
 51    * @author Andy Armstrong
 52    * @version $Revision: 577512 $, $Date: 2007-09-19 19:27:54 -0700 (Wed, 19 Sep 2007) $
 53    */
 54    public class TextQueryResolver extends SimpleConfigurable implements QueryResolver {
 55   
 56    public final static String STYLE_FT = "Text";
 57    private static final Log log = LogFactory.getLog(TextQueryResolver.class);
 58   
 59    private class TextQuery implements Query {
 60    private Collection context;
 61    private String query;
 62    private Key keys[];
 63    private LuceneIndexer idx;
 64    private org.apache.lucene.search.Query compiledQuery;
 65   
 66  26 private TextQuery(Collection context, String query, Key[] keys) throws QueryException {
 67  26 this.context = context;
 68  26 this.keys = keys;
 69  26 this.query = query;
 70   
 71  26 try {
 72  26 idx = findIndex(context);
 73  26 if (null == idx) {
 74  1 throw new QueryException(FaultCodes.QRY_STYLE_NOT_FOUND, "Could not find text indexer in this collection");
 75    }
 76  25 Analyzer an = idx.getAnalyzer();
 77  25 compiledQuery = new QueryParser("", an).parse(query);
 78    } catch (QueryException e) {
 79  1 throw e;
 80    } catch (DBException e) {
 81  0 throw new QueryException(FaultCodes.QRY_COMPILATION_ERROR, "Failed to compile the query due to database error", e);
 82    } catch (ParseException e) {
 83  0 throw new QueryException(FaultCodes.QRY_COMPILATION_ERROR, "Failed to compile the query", e);
 84    }
 85    }
 86   
 87  0 public String getQueryStyle() {
 88  0 return STYLE_FT;
 89    }
 90   
 91  0 public Collection getQueryContext() {
 92  0 return context;
 93    }
 94   
 95  0 public String getQueryString() {
 96  0 return query;
 97    }
 98   
 99  0 public NamespaceMap getNamespaceMap() {
 100  0 return null;
 101    }
 102   
 103  0 public Key[] getKeySet() {
 104  0 return keys;
 105    }
 106   
 107    /**
 108    * Executes compiled Lucene query against existing index.
 109    *
 110    * @return NodeSet that contains document element of all matching
 111    * documents
 112    * @throws QueryException
 113    */
 114  25 public NodeSet execute() throws QueryException {
 115  25 try {
 116  25 IndexMatch[] match = idx.queryMatches(compiledQuery);
 117  25 Key[] uniqueKeys = QueryEngine.getUniqueKeys(match);
 118   
 119    // convert keys filter to HashMap
 120  25 HashSet filter = null;
 121  25 if (keys != null) {
 122  1 filter = new HashSet(keys.length);
 123  1 for (int k = 0; k < keys.length; k++) {
 124  3 filter.add(keys[k]);
 125    }
 126    }
 127   
 128  25 Key rk[] = new Key[uniqueKeys.length];
 129  25 int rkused = 0;
 130  25 for (int i = 0; i < uniqueKeys.length; i++) {
 131  59 if (filter == null || filter.contains(uniqueKeys[i])) {
 132  58 rk[rkused++] = uniqueKeys[i];
 133    }
 134    }
 135   
 136  25 return new ResultSet(rk, rkused);
 137   
 138    } catch (DBException e) {
 139  0 throw new ProcessingException("Error executing full text query: " + e.getMessage(), e);
 140    }
 141    }
 142   
 143    /**
 144    * ResultSet
 145    */
 146    private class ResultSet implements NodeSet {
 147    private Key[] keySet;
 148   
 149    private int keyPos = 0;
 150    private int keyLen;
 151    private Node nextNode;
 152   
 153  25 public ResultSet(Key[] keySet, int keyLen) {
 154  25 this.keySet = keySet;
 155  25 this.keyLen = keyLen;
 156   
 157  25 try {
 158  25 prepareNextNode();
 159    } catch (Exception e) {
 160  0 throw new XindiceRuntimeException(e);
 161    }
 162    }
 163   
 164  83 private void prepareNextNode() throws DBException {
 165  83 nextNode = null;
 166   
 167  83 while (nextNode == null && keyPos < keyLen) {
 168  58 Entry entry = context.getEntry(keySet[keyPos++]);
 169  58 if (entry == null || entry.getEntryType() != Entry.DOCUMENT) {
 170  0 continue;
 171    }
 172   
 173  58 DBDocument d = (DBDocument) entry.getValue();
 174  58 if (d != null) {
 175  58 nextNode = d.getDocumentElement();
 176    }
 177    }
 178    }
 179   
 180  83 public boolean hasMoreNodes() {
 181  83 return nextNode != null;
 182    }
 183   
 184  58 public Object getNextNode() {
 185  58 Node n = nextNode;
 186   
 187  58 try {
 188  58 prepareNextNode();
 189    } catch (Exception e) {
 190  0 throw new XindiceRuntimeException(e);
 191    }
 192   
 193  58 return n;
 194    }
 195    }
 196    }
 197   
 198  26 private LuceneIndexer findIndex(Collection c) throws DBException {
 199  26 return (LuceneIndexer) c.getIndexManager().getBestIndexer(Indexer.STYLE_FULLTEXT, null);
 200    }
 201   
 202  3 public void setQueryEngine(QueryEngine engine) {
 203    // do nothing
 204    // FIXME: not used
 205    }
 206   
 207  3 public String getQueryStyle() {
 208  3 return STYLE_FT;
 209    }
 210   
 211  1 public Query compileQuery(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
 212  1 if (log.isTraceEnabled()) {
 213  0 log.trace("Compiling query for collection " + context.getCanonicalName() + ", query = " + query);
 214    }
 215   
 216  1 return new TextQuery(context, query, keys);
 217    }
 218   
 219  25 public NodeSet query(Collection context, String query, NamespaceMap nsMap, Key[] keys) throws QueryException {
 220  25 if (log.isTraceEnabled()) {
 221  0 log.trace("Querying collection " + context.getCanonicalName() + ", query = " + query);
 222    }
 223  25 try {
 224  25 Query tq = new TextQuery(context, query, keys);
 225  24 return tq.execute();
 226    } catch (Exception e) {
 227  1 if (e instanceof QueryException) {
 228  1 throw (QueryException) e;
 229    } else {
 230  0 throw new ProcessingException("Failed to execute text query", e);
 231    }
 232    }
 233    }
 234    }