001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.search.lucene.highlight;
016    
017    import java.util.HashSet;
018    import java.util.LinkedList;
019    import java.util.Set;
020    import java.util.concurrent.CopyOnWriteArrayList;
021    
022    import org.apache.lucene.index.Term;
023    import org.apache.lucene.search.BooleanClause;
024    import org.apache.lucene.search.BooleanQuery;
025    import org.apache.lucene.search.FilteredQuery;
026    import org.apache.lucene.search.Query;
027    import org.apache.lucene.search.highlight.WeightedTerm;
028    
029    /**
030     * @author Shuyang Zhou
031     */
032    public class QueryTermExtractor {
033    
034            public static WeightedTerm[] getTerms(
035                    Query query, boolean prohibited, String fieldName) {
036    
037                    if (query == null) {
038                            return _emptyWeightedTermArray;
039                    }
040    
041                    Set<WeightedTerm> weightedTerms = new HashSet<WeightedTerm>();
042    
043                    Set<Term> terms = new HashSet<Term>();
044    
045                    LinkedList<Query> queries = new LinkedList<Query>();
046    
047                    Query lastQuery = query;
048    
049                    while (lastQuery != null) {
050                            if (lastQuery instanceof BooleanQuery) {
051                                    BooleanQuery booleanQuery = (BooleanQuery)lastQuery;
052    
053                                    BooleanClause[] booleanClauses = booleanQuery.getClauses();
054    
055                                    for (BooleanClause booleanClause : booleanClauses) {
056                                            if (prohibited ||
057                                                    (booleanClause.getOccur() !=
058                                                            BooleanClause.Occur.MUST_NOT)) {
059    
060                                                    Query booleanClauseQuery = booleanClause.getQuery();
061    
062                                                    if (booleanClauseQuery != null) {
063                                                            queries.addFirst(booleanClauseQuery);
064                                                    }
065                                            }
066                                    }
067    
068                                    lastQuery = queries.poll();
069                            }
070                            else if (lastQuery instanceof FilteredQuery) {
071                                    FilteredQuery filteredQuery = (FilteredQuery)lastQuery;
072    
073                                    lastQuery = filteredQuery.getQuery();
074    
075                                    if (lastQuery == null) {
076                                            lastQuery = queries.poll();
077                                    }
078                            }
079                            else {
080                                    Class<? extends Query> queryClass = lastQuery.getClass();
081    
082                                    if (!_queryClasses.contains(queryClass)) {
083                                            try {
084                                                    lastQuery.extractTerms(terms);
085    
086                                                    for (Term term : terms) {
087                                                            if ((fieldName == null) ||
088                                                                    fieldName.equals(term.field())) {
089    
090                                                                    WeightedTerm weightedTerm = new WeightedTerm(
091                                                                            query.getBoost(), term.text());
092    
093                                                                    weightedTerms.add(weightedTerm);
094                                                            }
095                                                    }
096    
097                                                    terms.clear();
098                                            }
099                                            catch (UnsupportedOperationException uoe) {
100                                                    _queryClasses.addIfAbsent(queryClass);
101                                            }
102                                    }
103    
104                                    lastQuery = queries.poll();
105                            }
106                    }
107    
108                    return weightedTerms.toArray(new WeightedTerm[weightedTerms.size()]);
109            }
110    
111            private static WeightedTerm[] _emptyWeightedTermArray = new WeightedTerm[0];
112            private static CopyOnWriteArrayList<Class<? extends Query>> _queryClasses =
113                    new CopyOnWriteArrayList<Class<? extends Query>>();
114    
115    }