0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
0N/A
0N/A/*
0N/A * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/A
0N/Apackage org.opensolaris.opengrok.search.context;
376N/A
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.HashSet;
234N/Aimport java.util.List;
0N/Aimport java.util.Map;
0N/Aimport java.util.Set;
0N/Aimport org.apache.lucene.index.Term;
0N/Aimport org.apache.lucene.search.BooleanClause;
0N/Aimport org.apache.lucene.search.BooleanQuery;
0N/Aimport org.apache.lucene.search.PhraseQuery;
234N/Aimport org.apache.lucene.search.PrefixQuery;
234N/Aimport org.apache.lucene.search.Query;
0N/Aimport org.apache.lucene.search.TermQuery;
0N/Aimport org.apache.lucene.search.WildcardQuery;
350N/A
0N/A/**
0N/A * Utility class used to extract the terms used in a query
0N/A * This class will not find terms for MultiTermQuery, RangeQuery and PrefixQuery classes
0N/A * so the caller must pass a rewritten query (see query.rewrite) to obtain a list of
0N/A * expanded terms.
0N/A *
0N/A */
350N/Apublic final class QueryMatchers {
0N/A private Set<String> caseSensitiveTerms;
234N/A private Set<String> caseInsensitiveTerms;
125N/A private List<LineMatcher> matchers;
234N/A private Map<String, Boolean> fields;
234N/A /**
234N/A * Get the terms from a query and returs a list of DFAs which match
0N/A * a stream of tokens
0N/A *
0N/A * @param query the query to generate matchers for
226N/A * @param fields a map whose keys tell which fields to create matchers for,
0N/A * and whose values tell if the field is case insensitive (true) or
0N/A * case sensitive (false)
0N/A * @return list of LineMatching DFAs
0N/A */
0N/A public LineMatcher[] getMatchers(Query query, Map<String, Boolean> fields) {
0N/A caseSensitiveTerms = new HashSet<String>();
0N/A caseInsensitiveTerms = new HashSet<String>();
0N/A matchers = new ArrayList<LineMatcher>();
0N/A this.fields = fields;
0N/A getTerms(query);
0N/A if (!caseSensitiveTerms.isEmpty()) {
0N/A matchers.add(0, new TokenSetMatcher(caseSensitiveTerms, false));
0N/A }
0N/A if (!caseInsensitiveTerms.isEmpty()) {
0N/A matchers.add(0, new TokenSetMatcher(caseInsensitiveTerms, true));
0N/A }
0N/A if (matchers.isEmpty()) {
0N/A return null;
0N/A }
0N/A LineMatcher[] m = matchers.toArray(new LineMatcher[matchers.size()]);
0N/A return (m);
0N/A }
0N/A
0N/A private void getTerms(Query query) {
0N/A if (query instanceof BooleanQuery) {
0N/A getBooleans((BooleanQuery) query);
0N/A } else if (query instanceof PhraseQuery) {
0N/A getPhrases((PhraseQuery) query);
0N/A } else if (query instanceof WildcardQuery) {
0N/A getWildTerm((WildcardQuery) query);
0N/A } else if (query instanceof TermQuery) {
0N/A getTerm((TermQuery) query);
234N/A } else if (query instanceof PrefixQuery) {
0N/A getPrefix((PrefixQuery) query);
0N/A }
0N/A }
0N/A
0N/A private void getBooleans(BooleanQuery query) {
0N/A BooleanClause[] queryClauses = query.getClauses();
0N/A for (int i = 0; i < queryClauses.length; i++) {
0N/A if (!queryClauses[i].isProhibited()) {
0N/A getTerms(queryClauses[i].getQuery());
234N/A }
0N/A }
234N/A }
234N/A
234N/A private void getPhrases(PhraseQuery query) {
0N/A Term[] queryTerms = query.getTerms();
0N/A if (queryTerms.length > 0 && useTerm(queryTerms[0])) {
0N/A boolean caseInsensitive = isCaseInsensitive(queryTerms[0]);
0N/A String[] termsArray = new String[queryTerms.length];
0N/A for (int i = 0; i < queryTerms.length; i++) {
0N/A termsArray[i] = queryTerms[i].text();
99N/A }
125N/A matchers.add(new PhraseMatcher(termsArray, caseInsensitive));
234N/A }
234N/A }
236N/A
236N/A private void getTerm(TermQuery query) {
236N/A Term term = query.getTerm();
236N/A if (useTerm(term)) {
236N/A String text = term.text();
236N/A if (isCaseInsensitive(term)) {
236N/A caseInsensitiveTerms.add(text);
236N/A } else {
236N/A caseSensitiveTerms.add(text);
236N/A }
236N/A }
236N/A }
236N/A
236N/A private void getWildTerm(WildcardQuery query) {
234N/A Term term = query.getTerm();
234N/A if (useTerm(term)) {
235N/A matchers.add(
235N/A new WildCardMatcher(term.text(), isCaseInsensitive(term)));
235N/A }
235N/A }
235N/A
235N/A private void getPrefix(PrefixQuery query) {
235N/A Term term = query.getPrefix();
235N/A if (useTerm(term)) {
235N/A matchers.add(
235N/A new PrefixMatcher(term.text(), isCaseInsensitive(term)));
235N/A }
235N/A }
235N/A
235N/A /**
235N/A * Check whether a matcher should be created for a term.
0N/A */
0N/A private boolean useTerm(Term term) {
0N/A return fields.keySet().contains(term.field());
0N/A }
0N/A
0N/A /**
234N/A * Check if a term should be matched in a case-insensitive manner. Should
0N/A * only be called on terms for which {@link #useTerm(Term)} returns true.
0N/A */
235N/A private boolean isCaseInsensitive(Term term) {
235N/A return fields.get(term.field());
234N/A }
235N/A}
226N/A