/*
    A QueryParser which handles searching on multiple fields.
    Copyright (C) 2001  Kelvin Tan

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.queryParser.QueryParserTokenManager;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;

import java.io.InputStream;
import java.io.Reader;

/**
 * A QueryParser which searches multiple fields.
 *
 * @author <a href="mailto:kelvin@relevanz.com">Kelvin Tan</a>
 * @version $Revision: 1.1 $
 */
public class MultiFieldQueryParser extends QueryParser
{
    public static final int NORMAL_FIELD = 0;
    public static final int REQUIRED_FIELD = 1;
    public static final int PROHIBITED_FIELD = 2;

    public MultiFieldQueryParser(InputStream stream)
    {
        super(stream);
    }

    public MultiFieldQueryParser(QueryParserTokenManager tm)
    {
        super(tm);
    }

    public MultiFieldQueryParser(Reader stream)
    {
        super(stream);
    }

    public MultiFieldQueryParser(String f, Analyzer a)
    {
        super(f, a);
    }

    /**
     * <p>
     * Parses a query, searching on the fields specified.
     * <p>
     * If x fields are specified, this effectively constructs:
     * <pre>
     * <code>
     * ({field1}:{query}) ({field2}:{query}) ({field3}:{query})...({fieldx}:{query})
     * </code>
     * </pre>
     *
     * @param query Query string to parse
     * @param fields Fields to search on
     * @param analyzer Analyzer to use
     */
    public static Query parse(String query, String[] fields, Analyzer analyzer) throws ParseException
    {
        BooleanQuery bQuery = new BooleanQuery();
        for (int i = 0; i < fields.length; i++)
        {
            Query q = parse(query, fields[i], analyzer);
            bQuery.add(q, false, false);
        }
        return bQuery;
    }

    /**
     * <p>
     * Parses a query, searching on the fields specified.
     * Use this if you need to specify certain fields as required,
     * and others as prohibited.
     * <p><pre>
     * Usage:
     * <code>
     * String[] fields = {"filename", "contents", "description"};
     * int[] flags = {MultiFieldQueryParser.NORMAL_FIELD,
     *                MultiFieldQueryParser.REQUIRED_FIELD,
     *                MultiFieldQueryParser.PROHIBITED_FIELD,};
     * parse(query, fields, flags, analyzer);
     * </code>
     * </pre>
     *<p>
     * The code above would construct a query:
     * <pre>
     * <code>
     * (filename:{query}) +(contents:{query}) -(description:{query})
     * </code>
     * </pre>
     *
     * @param query Query string to parse
     * @param fields Fields to search on
     * @param flags Flags describing the fields
     * @param analyzer Analyzer to use
     */
    public static Query parse(String query, String[] fields, int[] flags, Analyzer analyzer) throws ParseException
    {
        BooleanQuery bQuery = new BooleanQuery();
        for (int i = 0; i < fields.length; i++)
        {
            Query q = parse(query, fields[i], analyzer);
            int flag = flags[i];
            switch (flag)
            {
            case NORMAL_FIELD:
                bQuery.add(q, false, false);break;
            case REQUIRED_FIELD:
                bQuery.add(q, true, false);break;
            case PROHIBITED_FIELD:
                bQuery.add(q, false, true);break;
            }
        }
        return bQuery;
    }
}

