extensions/net.sf.basedb.varsearch/trunk/src/net/sf/basedb/varsearch/query/LuceneQueryFactory.java

Code
Comments
Other
Rev Date Author Line
6132 16 Feb 21 nicklas 1 package net.sf.basedb.varsearch.query;
6109 25 Jan 21 nicklas 2
6546 24 Jan 22 nicklas 3 import java.io.IOException;
6109 25 Jan 21 nicklas 4 import java.util.ArrayList;
6111 29 Jan 21 nicklas 5 import java.util.Collection;
6109 25 Jan 21 nicklas 6 import java.util.List;
6245 24 May 21 nicklas 7 import java.util.regex.Matcher;
6245 24 May 21 nicklas 8 import java.util.regex.Pattern;
6109 25 Jan 21 nicklas 9
6136 18 Feb 21 nicklas 10 import org.apache.lucene.document.IntPoint;
6522 20 Dec 21 nicklas 11 import org.apache.lucene.queryparser.classic.ParseException;
6109 25 Jan 21 nicklas 12 import org.apache.lucene.queryparser.classic.QueryParser;
6141 19 Feb 21 nicklas 13 import org.apache.lucene.search.BooleanClause;
6141 19 Feb 21 nicklas 14 import org.apache.lucene.search.BooleanQuery;
6109 25 Jan 21 nicklas 15 import org.apache.lucene.search.Query;
6138 18 Feb 21 nicklas 16 import org.slf4j.LoggerFactory;
6109 25 Jan 21 nicklas 17
6136 18 Feb 21 nicklas 18 import net.sf.basedb.core.BaseException;
6144 23 Feb 21 nicklas 19 import net.sf.basedb.core.Item;
6109 25 Jan 21 nicklas 20 import net.sf.basedb.core.ItemContext;
6136 18 Feb 21 nicklas 21 import net.sf.basedb.core.Operator;
6109 25 Jan 21 nicklas 22 import net.sf.basedb.core.PropertyFilter;
6109 25 Jan 21 nicklas 23 import net.sf.basedb.core.query.IdListRestriction;
6109 25 Jan 21 nicklas 24 import net.sf.basedb.core.query.QueryFilterAction;
6109 25 Jan 21 nicklas 25 import net.sf.basedb.core.query.Restriction;
6141 19 Feb 21 nicklas 26 import net.sf.basedb.util.Values;
6109 25 Jan 21 nicklas 27 import net.sf.basedb.util.extensions.ActionFactory;
6109 25 Jan 21 nicklas 28 import net.sf.basedb.util.extensions.ClientContext;
6109 25 Jan 21 nicklas 29 import net.sf.basedb.util.extensions.InvokationContext;
7074 24 Mar 23 nicklas 30 import net.sf.basedb.util.extensions.logging.ExtensionsLog;
7074 24 Mar 23 nicklas 31 import net.sf.basedb.util.extensions.logging.ExtensionsLogger;
6848 17 Oct 22 nicklas 32 import net.sf.basedb.varsearch.VarSearch;
6132 16 Feb 21 nicklas 33 import net.sf.basedb.varsearch.index.LuceneIndex;
6544 19 Jan 22 nicklas 34 import net.sf.basedb.varsearch.index.LuceneIndex.Status;
6111 29 Jan 21 nicklas 35 import net.sf.basedb.varsearch.service.VarSearchService;
6109 25 Jan 21 nicklas 36
6132 16 Feb 21 nicklas 37 /**
6132 16 Feb 21 nicklas 38   Extension that adds support for querying Lucene indexes in a BASE ItemQuery.
6132 16 Feb 21 nicklas 39   The extension is triggered on and handles PropertyFilter:s with prefix
6132 16 Feb 21 nicklas 40   !x.lucene. The query against the Lucene index is expected to return a list
6132 16 Feb 21 nicklas 41   of RawBioAssay ID values that are then passed on to BASE as an IdListRestriction.
6132 16 Feb 21 nicklas 42   
6132 16 Feb 21 nicklas 43   @author nicklas
6132 16 Feb 21 nicklas 44 */
6109 25 Jan 21 nicklas 45 public class LuceneQueryFactory 
6109 25 Jan 21 nicklas 46   implements ActionFactory<QueryFilterAction>
6109 25 Jan 21 nicklas 47 {
7074 24 Mar 23 nicklas 48   
7074 24 Mar 23 nicklas 49   /**
7074 24 Mar 23 nicklas 50     The ID of the query extension.
7074 24 Mar 23 nicklas 51     @since 1.8
7074 24 Mar 23 nicklas 52   */
7074 24 Mar 23 nicklas 53   public static final String ID = "net.sf.basedb.varsearch.lucene-query";
7074 24 Mar 23 nicklas 54   
7074 24 Mar 23 nicklas 55   private static final ExtensionsLogger logger = 
7074 24 Mar 23 nicklas 56       ExtensionsLog.getLogger(ID, true).wrap(LoggerFactory.getLogger(LuceneQueryFactory.class));
6109 25 Jan 21 nicklas 57
7074 24 Mar 23 nicklas 58   
6109 25 Jan 21 nicklas 59   public LuceneQueryFactory()
6109 25 Jan 21 nicklas 60   {}
6109 25 Jan 21 nicklas 61   
6109 25 Jan 21 nicklas 62   @Override
6109 25 Jan 21 nicklas 63   public boolean prepareContext(InvokationContext<? super QueryFilterAction> context) 
6109 25 Jan 21 nicklas 64   {
6111 29 Jan 21 nicklas 65     // We need the service to provide us with information about existing 
6111 29 Jan 21 nicklas 66     // indexes and IndexReader/IndexSearcher instances
6111 29 Jan 21 nicklas 67     ItemContext ctx = context.getClientContext().getCurrentItem();
6144 23 Feb 21 nicklas 68     return ctx.getItemType() == Item.RAWBIOASSAY && 
6144 23 Feb 21 nicklas 69       ctx.hasExtensionFilter("lucene") && 
6144 23 Feb 21 nicklas 70       VarSearchService.getInstance().isRunning();
6109 25 Jan 21 nicklas 71   }
6109 25 Jan 21 nicklas 72
6109 25 Jan 21 nicklas 73   @Override
6109 25 Jan 21 nicklas 74   public QueryFilterAction[] getActions(InvokationContext<? super QueryFilterAction> context) 
6109 25 Jan 21 nicklas 75   {
6109 25 Jan 21 nicklas 76     try
6109 25 Jan 21 nicklas 77     {
6109 25 Jan 21 nicklas 78       ClientContext cc = context.getClientContext();
6111 29 Jan 21 nicklas 79       ItemContext ctx = cc.getCurrentItem();
6109 25 Jan 21 nicklas 80       
6111 29 Jan 21 nicklas 81       Collection<LuceneIndex> indexes = VarSearchService.getInstance().getIndexes();
6111 29 Jan 21 nicklas 82       List<QueryFilterAction> actions = new ArrayList<>(indexes.size());
6111 29 Jan 21 nicklas 83
6111 29 Jan 21 nicklas 84       // Create actions for indexes that has a column with a filter
6111 29 Jan 21 nicklas 85       for (LuceneIndex idx : indexes)
6111 29 Jan 21 nicklas 86       {
6544 19 Jan 22 nicklas 87         if (idx.getQueryStatus() != Status.ENABLED) continue;
6544 19 Jan 22 nicklas 88
6111 29 Jan 21 nicklas 89         if (ctx.hasExtensionFilter("lucene."+idx.getId()))
6111 29 Jan 21 nicklas 90         {
6546 24 Jan 22 nicklas 91           LuceneFilterAction<?> action = idx.createFilterAction(context);
6546 24 Jan 22 nicklas 92           if (action != null)
6546 24 Jan 22 nicklas 93           {
6546 24 Jan 22 nicklas 94             // Save the action so that it can be picked up by
6546 24 Jan 22 nicklas 95             // a ListColumnFilter when displaying results
6546 24 Jan 22 nicklas 96             cc.setAttribute("lucene-filter-"+idx.getId(), action);
6546 24 Jan 22 nicklas 97             actions.add(action);
6546 24 Jan 22 nicklas 98           }
6111 29 Jan 21 nicklas 99         }
6111 29 Jan 21 nicklas 100       }
6546 24 Jan 22 nicklas 101       return actions.size() == 0 ? null : actions.toArray(new QueryFilterAction[actions.size()]);
6109 25 Jan 21 nicklas 102     }
6109 25 Jan 21 nicklas 103     catch (Exception ex)
6109 25 Jan 21 nicklas 104     {
6848 17 Oct 22 nicklas 105       VarSearch.throwRuntimException(ex);
6109 25 Jan 21 nicklas 106     }
6848 17 Oct 22 nicklas 107     return null;
6109 25 Jan 21 nicklas 108   }
6109 25 Jan 21 nicklas 109
6546 24 Jan 22 nicklas 110   /**
6546 24 Jan 22 nicklas 111     Base class for filter actions. Subclasses need to implement som query functionality.
6546 24 Jan 22 nicklas 112   */
6546 24 Jan 22 nicklas 113   public abstract static class LuceneFilterAction<I extends LuceneIndex>
6109 25 Jan 21 nicklas 114     implements QueryFilterAction
6109 25 Jan 21 nicklas 115   {
6260 27 May 21 nicklas 116     /**
6260 27 May 21 nicklas 117       Match a query string ending with #DD where DD is digits that change
6260 27 May 21 nicklas 118       the timeout.
6260 27 May 21 nicklas 119     */
6260 27 May 21 nicklas 120     private static final Pattern QUERY_WITH_TIMEOUT = Pattern.compile("(.*)\\#(\\d+)$");
6245 24 May 21 nicklas 121     private static final int DEFAULT_TIMEOUT = 30;
6245 24 May 21 nicklas 122     private static final int MAX_TIMEOUT = 600;
6245 24 May 21 nicklas 123     
6546 24 Jan 22 nicklas 124     protected final I idx;
6546 24 Jan 22 nicklas 125     protected final ItemContext context;
6546 24 Jan 22 nicklas 126     protected final QueryParser parser;
6109 25 Jan 21 nicklas 127     private final List<Query> queries;
6109 25 Jan 21 nicklas 128     
6548 24 Jan 22 nicklas 129     private QueryResult mergedResult;
6548 24 Jan 22 nicklas 130     private QueryResult lastResult;
6241 21 May 21 nicklas 131     
6546 24 Jan 22 nicklas 132     protected LuceneFilterAction(ItemContext context, I idx) 
6109 25 Jan 21 nicklas 133     {
6111 29 Jan 21 nicklas 134       this.idx = idx;
6546 24 Jan 22 nicklas 135       this.context = context;
6119 05 Feb 21 nicklas 136       this.parser = idx.createQueryParser();
6236 18 May 21 nicklas 137       this.queries = new ArrayList<>();
6109 25 Jan 21 nicklas 138     }
6109 25 Jan 21 nicklas 139     
6236 18 May 21 nicklas 140     /**
6236 18 May 21 nicklas 141       Get the Lucene queries for this column. The list typically contain
6236 18 May 21 nicklas 142       a single query, but may have more if multiple filter rows are used.
6236 18 May 21 nicklas 143     */
6236 18 May 21 nicklas 144     public List<Query> getQueries()
6236 18 May 21 nicklas 145     {
6236 18 May 21 nicklas 146       return queries;
6236 18 May 21 nicklas 147     }
6236 18 May 21 nicklas 148     
6236 18 May 21 nicklas 149     /**
6522 20 Dec 21 nicklas 150       Add a query to the filter.
6522 20 Dec 21 nicklas 151       @since 1.4
6522 20 Dec 21 nicklas 152     */
6522 20 Dec 21 nicklas 153     public void addQuery(String query)
6522 20 Dec 21 nicklas 154       throws ParseException
6522 20 Dec 21 nicklas 155     {
6522 20 Dec 21 nicklas 156       queries.add(parser.parse(query));
6522 20 Dec 21 nicklas 157     }
6522 20 Dec 21 nicklas 158     
6522 20 Dec 21 nicklas 159     /**
6241 21 May 21 nicklas 160       Get the result of the query.
6241 21 May 21 nicklas 161     */
6241 21 May 21 nicklas 162     public QueryResult getQueryResult()
6241 21 May 21 nicklas 163     {
6548 24 Jan 22 nicklas 164       return mergedResult == null ? lastResult : mergedResult;
6241 21 May 21 nicklas 165     }
6241 21 May 21 nicklas 166     
6241 21 May 21 nicklas 167     /**
6236 18 May 21 nicklas 168       Get the current item context.
6236 18 May 21 nicklas 169     */
6236 18 May 21 nicklas 170     public ItemContext getItemContext()
6236 18 May 21 nicklas 171     {
6236 18 May 21 nicklas 172       return context;
6236 18 May 21 nicklas 173     }
6236 18 May 21 nicklas 174     
6109 25 Jan 21 nicklas 175     @Override
6109 25 Jan 21 nicklas 176     public Restriction getColumnRestriction(PropertyFilter filter) 
6109 25 Jan 21 nicklas 177     {
6111 29 Jan 21 nicklas 178       // Note that this method is called for EVERY column with a filter
6111 29 Jan 21 nicklas 179       // we need to check that it should be handled here. 
6111 29 Jan 21 nicklas 180       // Also note that there can be multiple filter rows with a filter
6111 29 Jan 21 nicklas 181       // in this column
6111 29 Jan 21 nicklas 182       if (!filter.isExtensionFilter("lucene."+idx.getId())) return null;
6109 25 Jan 21 nicklas 183       
6136 18 Feb 21 nicklas 184       Operator op = filter.getOperator();
6141 19 Feb 21 nicklas 185       String queryString = filter.getValue();
6548 24 Jan 22 nicklas 186       if (mergedResult == null && lastResult != null)
6548 24 Jan 22 nicklas 187       {
6548 24 Jan 22 nicklas 188         mergedResult = new QueryResult(lastResult);
6548 24 Jan 22 nicklas 189       }
6548 24 Jan 22 nicklas 190       this.lastResult = null;
6141 19 Feb 21 nicklas 191       boolean notInList = false; // If items that are NOT in the returned list should be selected or not
6109 25 Jan 21 nicklas 192       try
6109 25 Jan 21 nicklas 193       {
6137 18 Feb 21 nicklas 194         QueryCache cache = idx.getQueryCache();
6137 18 Feb 21 nicklas 195         
6109 25 Jan 21 nicklas 196         // Parse filter text to query
6136 18 Feb 21 nicklas 197         Query query = null;
6245 24 May 21 nicklas 198         int timeoutInSeconds = DEFAULT_TIMEOUT;
6141 19 Feb 21 nicklas 199         String rbaIdField = "rbaId";
6141 19 Feb 21 nicklas 200         if (queryString == null || "%".equals(queryString))
6136 18 Feb 21 nicklas 201         {
6136 18 Feb 21 nicklas 202           // This is a filter for loading all Rawbioassays in the index
6136 18 Feb 21 nicklas 203           // We do not save this in 'queries' since it is not a search for
6141 19 Feb 21 nicklas 204           // variants, but the result is cached under '%'
6546 24 Jan 22 nicklas 205           query = createAllRawBioAssaysQuery();
6141 19 Feb 21 nicklas 206           rbaIdField = "mainId";
6141 19 Feb 21 nicklas 207           // '%' should be equivalent to '<>' and '<>%' equivalent to '='
6141 19 Feb 21 nicklas 208           notInList = op.isNegationOperator() ^ (queryString == null);
6136 18 Feb 21 nicklas 209         }
6141 19 Feb 21 nicklas 210         else if (queryString.matches("\\d+"))
6141 19 Feb 21 nicklas 211         {
6141 19 Feb 21 nicklas 212           int value = Values.getInt(queryString);
6546 24 Jan 22 nicklas 213           query = createNumVariantsQuery(value, op);
6141 19 Feb 21 nicklas 214           rbaIdField = "mainId";
6141 19 Feb 21 nicklas 215         }
6136 18 Feb 21 nicklas 216         else
6136 18 Feb 21 nicklas 217         {
6141 19 Feb 21 nicklas 218           if (op != Operator.EQ)
6141 19 Feb 21 nicklas 219           {
6141 19 Feb 21 nicklas 220             throw new BaseException("Only '=' operator is supported");
6141 19 Feb 21 nicklas 221           }
6245 24 May 21 nicklas 222           Matcher m = QUERY_WITH_TIMEOUT.matcher(queryString);
6245 24 May 21 nicklas 223           if (m.matches())
6245 24 May 21 nicklas 224           {
6245 24 May 21 nicklas 225             timeoutInSeconds = Math.min(Values.getInt(m.group(2)), MAX_TIMEOUT);
6245 24 May 21 nicklas 226             queryString = m.group(1);
6245 24 May 21 nicklas 227           }
6546 24 Jan 22 nicklas 228           
6546 24 Jan 22 nicklas 229           query = createVariantQuery(queryString);
6136 18 Feb 21 nicklas 230           queries.add(query);
6136 18 Feb 21 nicklas 231         }
6541 17 Jan 22 nicklas 232
6138 18 Feb 21 nicklas 233         logger.debug("Index: " + idx.getName());
6138 18 Feb 21 nicklas 234         logger.debug("QueryString: " + queryString);
6138 18 Feb 21 nicklas 235         logger.debug("Query: " + query);
6245 24 May 21 nicklas 236         logger.debug("Timeout: " + timeoutInSeconds+"s");
6138 18 Feb 21 nicklas 237         
6109 25 Jan 21 nicklas 238         // Search and collect RawBioassay ID values
6548 24 Jan 22 nicklas 239         lastResult = cache.get(queryString, timeoutInSeconds);
6548 24 Jan 22 nicklas 240         if (lastResult == null)
6137 18 Feb 21 nicklas 241         {
6137 18 Feb 21 nicklas 242           long time = -System.currentTimeMillis();
6553 27 Jan 22 nicklas 243           RawBioAssayIdCollectorManager manager = new RawBioAssayIdCollectorManager(rbaIdField, timeoutInSeconds);
6548 24 Jan 22 nicklas 244           lastResult = idx.getIndexSearcher().search(query, manager);
6241 21 May 21 nicklas 245           
6137 18 Feb 21 nicklas 246           time += System.currentTimeMillis();
6548 24 Jan 22 nicklas 247           logger.debug("Hits: " + lastResult.getHits());
6138 18 Feb 21 nicklas 248           logger.debug("Time: " + time);
6548 24 Jan 22 nicklas 249           if (lastResult.hasTimedOut())
6241 21 May 21 nicklas 250           {
6548 24 Jan 22 nicklas 251             logger.debug("Timeout: "+lastResult.getTimeoutInSeconds()+"s");
6548 24 Jan 22 nicklas 252             logger.debug("Documents after timeout: " + lastResult.getDocumentsAfterTimeout());
6548 24 Jan 22 nicklas 253             logger.debug("Total documents: " + lastResult.getTotalDocuments());
6241 21 May 21 nicklas 254           }
6246 24 May 21 nicklas 255           // Store query result in cache if it takes more than 100ms to execute
6548 24 Jan 22 nicklas 256           if (time > 100) cache.store(queryString, lastResult);
6137 18 Feb 21 nicklas 257         }
6138 18 Feb 21 nicklas 258         else
6138 18 Feb 21 nicklas 259         {
6548 24 Jan 22 nicklas 260           logger.debug("Cached hits: " + lastResult.getHits());
6138 18 Feb 21 nicklas 261         }
6548 24 Jan 22 nicklas 262         
6548 24 Jan 22 nicklas 263         if (mergedResult != null) mergedResult.mergeResults(lastResult);
6109 25 Jan 21 nicklas 264       }
6109 25 Jan 21 nicklas 265       catch (Exception ex)
6109 25 Jan 21 nicklas 266       {
6138 18 Feb 21 nicklas 267         logger.debug("Could not execute query: " + queryString, ex);
6848 17 Oct 22 nicklas 268         VarSearch.throwRuntimException(ex);
6109 25 Jan 21 nicklas 269       }
6111 29 Jan 21 nicklas 270       
6136 18 Feb 21 nicklas 271       // Return the RawBioassay ID:s as a restriction: rba.id (NOT) IN (....)
6132 16 Feb 21 nicklas 272       // Note that we can't return null if there is no match since then everything would match
6548 24 Jan 22 nicklas 273       return new IdListRestriction(notInList, lastResult.getIdList());
6109 25 Jan 21 nicklas 274     }
6109 25 Jan 21 nicklas 275   
6132 16 Feb 21 nicklas 276     /**
6132 16 Feb 21 nicklas 277       Not used.
6132 16 Feb 21 nicklas 278     */
6109 25 Jan 21 nicklas 279     @Override
6109 25 Jan 21 nicklas 280     public Restriction getRowRestriction(int rowIndex)
6109 25 Jan 21 nicklas 281     {
6109 25 Jan 21 nicklas 282       return null;
6109 25 Jan 21 nicklas 283     }
6109 25 Jan 21 nicklas 284
6132 16 Feb 21 nicklas 285     /**
6132 16 Feb 21 nicklas 286       Not used.
6132 16 Feb 21 nicklas 287     */
6109 25 Jan 21 nicklas 288     @Override
6109 25 Jan 21 nicklas 289     public Restriction getQueryRestriction() 
6109 25 Jan 21 nicklas 290     {
6109 25 Jan 21 nicklas 291       return null;
6109 25 Jan 21 nicklas 292     }
6524 20 Dec 21 nicklas 293     
6524 20 Dec 21 nicklas 294     /**
6546 24 Jan 22 nicklas 295       Create a query that matches all raw bioassays. The defaul
6546 24 Jan 22 nicklas 296       implementation will return all documents having a mainId value
6546 24 Jan 22 nicklas 297       between 1 and Integer.MAX_VALUE.
6524 20 Dec 21 nicklas 298     */
6546 24 Jan 22 nicklas 299     protected Query createAllRawBioAssaysQuery()
6524 20 Dec 21 nicklas 300     {
6546 24 Jan 22 nicklas 301       return IntPoint.newRangeQuery("mainId", 1, Integer.MAX_VALUE);
6524 20 Dec 21 nicklas 302     }
6546 24 Jan 22 nicklas 303     
6546 24 Jan 22 nicklas 304     /**
6546 24 Jan 22 nicklas 305       Create a query that return raw bioassays based on the number of 
6546 24 Jan 22 nicklas 306       variants.
6546 24 Jan 22 nicklas 307     */
6546 24 Jan 22 nicklas 308     protected Query createNumVariantsQuery(int value, Operator op)
6546 24 Jan 22 nicklas 309     {
6546 24 Jan 22 nicklas 310       Query query = null;
6546 24 Jan 22 nicklas 311       if (op == Operator.EQ)
6546 24 Jan 22 nicklas 312       {
6546 24 Jan 22 nicklas 313         query = IntPoint.newRangeQuery("numVariants", value, value);
6546 24 Jan 22 nicklas 314       }
6546 24 Jan 22 nicklas 315       else if (op == Operator.NEQ)
6546 24 Jan 22 nicklas 316       {
6546 24 Jan 22 nicklas 317         BooleanQuery.Builder builder = new BooleanQuery.Builder();
6546 24 Jan 22 nicklas 318         builder.setMinimumNumberShouldMatch(1);
6546 24 Jan 22 nicklas 319         builder.add(IntPoint.newRangeQuery("numVariants", 0, value-1), BooleanClause.Occur.SHOULD);
6546 24 Jan 22 nicklas 320         builder.add(IntPoint.newRangeQuery("numVariants", value+1, Integer.MAX_VALUE), BooleanClause.Occur.SHOULD);
6546 24 Jan 22 nicklas 321         query = builder.build();
6546 24 Jan 22 nicklas 322       }
6546 24 Jan 22 nicklas 323       else if (op == Operator.GTEQ)
6546 24 Jan 22 nicklas 324       {
6546 24 Jan 22 nicklas 325         query = IntPoint.newRangeQuery("numVariants", value, Integer.MAX_VALUE);
6546 24 Jan 22 nicklas 326       }
6546 24 Jan 22 nicklas 327       else if (op == Operator.GT)
6546 24 Jan 22 nicklas 328       {
6546 24 Jan 22 nicklas 329         query = IntPoint.newRangeQuery("numVariants", value+1, Integer.MAX_VALUE);
6546 24 Jan 22 nicklas 330       }
6546 24 Jan 22 nicklas 331       else if (op == Operator.LT)
6546 24 Jan 22 nicklas 332       {
6546 24 Jan 22 nicklas 333         query = IntPoint.newRangeQuery("numVariants", 0, value-1);
6546 24 Jan 22 nicklas 334       }
6546 24 Jan 22 nicklas 335       else if (op == Operator.LTEQ)
6546 24 Jan 22 nicklas 336       {
6546 24 Jan 22 nicklas 337         query = IntPoint.newRangeQuery("numVariants", 0, value);
6546 24 Jan 22 nicklas 338       }
6546 24 Jan 22 nicklas 339       return query;
6546 24 Jan 22 nicklas 340     }
6546 24 Jan 22 nicklas 341     
6546 24 Jan 22 nicklas 342     /**
6546 24 Jan 22 nicklas 343       Create a query that searches for rawbioassays that have variants
6546 24 Jan 22 nicklas 344       matching the query string.
6546 24 Jan 22 nicklas 345     */
6546 24 Jan 22 nicklas 346     protected abstract Query createVariantQuery(String queryString)
6546 24 Jan 22 nicklas 347       throws ParseException, IOException;
6131 15 Feb 21 nicklas 348
6546 24 Jan 22 nicklas 349
6550 25 Jan 22 nicklas 350     /**
6550 25 Jan 22 nicklas 351       Collect document hits for the given raw bioassay under the current
6550 25 Jan 22 nicklas 352       filter settings.
6550 25 Jan 22 nicklas 353       @return Normally, the same collector that was passed, but it may also be a different one
6550 25 Jan 22 nicklas 354     */
6550 25 Jan 22 nicklas 355     public abstract AllDocsCollector getRawBioAssayHits(int rbaId, AllDocsCollector hits);
6550 25 Jan 22 nicklas 356     
6109 25 Jan 21 nicklas 357   }
6131 15 Feb 21 nicklas 358   
6109 25 Jan 21 nicklas 359 }