/*
 * $Header: /home/cvspublic/jakarta-slide/src/stores/org/apache/slide/index/TextContainsExpression.java,v 1.3 2004/09/13 16:52:23 unico Exp $
 * $Revision: 1.3 $
 * $Date: 2004/09/13 16:52:23 $
 *
 * ====================================================================
 *
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.apache.slide.index;

import org.apache.slide.search.basic.*;
import org.apache.slide.search.BadQueryException;
import org.apache.slide.search.SearchException;
import org.apache.slide.search.RequestedResource;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.common.SlideException;
import org.apache.slide.common.Domain;
import org.apache.slide.util.logger.Logger;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Hits;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.document.Document;

import java.util.Collection;

/**
 * Date: Jun 24, 2004
 * Time: 11:45:30 PM
 */
public class TextContainsExpression implements IBasicExpression {

    protected static final String LOG_CHANNEL = TextContainsExpression.class.getName();

    String searchedText;
    String indexPath;
    Analyzer analyzer;

    /** backptr to the factory */
    IBasicExpressionFactory factory;

    /**
     * constructor for a compare expression like gt, eq, ...
     * For your concrete implementation you are free, which parameters have to
     * be passed, let the factory give you everything you need.
     */
    TextContainsExpression (String searchedText, String rootPath, Analyzer analyzer)
    {
        this.searchedText = searchedText;
        this.indexPath = rootPath;
        this.analyzer = analyzer;
    }

    /**
     * constructor for a merge expression
     */
    TextContainsExpression (String mergeOperator,
                                      Collection children,
                                      IBasicExpressionFactory factory)
        throws BadQueryException
    {
        //        this.factory = factory;
        //        Iterator it = children.iterator();
        //        BasicExpressionTxtContainsSample firstChild = (BasicExpressionTxtContainsSample)it.next();
        //
        //        if (firstChild == null)
        //            throw new BadQueryException (mergeOperator + " needs at least one nested element");
        //
        //        theExecutableCommand = firstChild.theExecutableCommand;
        //
        //        // create the executable command
        //        while (it.hasNext()) {
        //            BasicExpressionTxtContainsSample exp = (BasicExpressionTxtContainsSample)it.next();
        //            theExecutableCommand += " " + mergeOperator + " " + exp.theExecutableCommand;
        //        }
    }

    /**
     * Search the index for this expression using Lucene.
     *
     * @return   an IBasicResultSet
     *
     * @throws   org.apache.slide.search.SearchException
     *
     */
    public IBasicResultSet execute() throws SearchException
    {
        IBasicResultSet result = new BasicResultSetImpl (false);

        try
        {
            Searcher searcher = new IndexSearcher(indexPath);

            Query query = QueryParser.parse(searchedText, TextContentIndexer.CONTENT_TEXT, analyzer);
            Hits hits = searcher.search (query);
            int noOfHits = hits.length();

            for (int i = 0; i < noOfHits; i++)
            {
                Document doc = hits.doc(i);
                String uri = doc.get(TextContentIndexer.URI_FIELD);

                IBasicQuery q = factory.getQuery();
                String scope = q.getSearchToken().getSlideContext().getSlidePath(q.getScope().getHref());
                if (uri.startsWith(scope)) {
                    RequestedResource resource = createResource(uri);
                    result.add (resource);
                }
            }
        }
        catch (Exception e)
        {
            throw new SearchException (e);
        }

        Domain.log(
            "Executed Search for '" + searchedText + "' in the index",
            LOG_CHANNEL,
            Logger.INFO);

        return  result;
    }

    private RequestedResource createResource(String uri) throws SearchException
    {
        ObjectNode node = new SubjectNode(uri); // this will return the root folder
        RequestedResource resource = null;
        IBasicQuery query = factory.getQuery();

        try
        {
            resource = new ComparableResourceImpl
                (node, query.getSearchToken(), query.getScope(),
                 factory.getPropertyProvider());
        }
        catch (SlideException e)
        {
            throw new SearchException (e);
        }
        return resource;
    }

    public void setFactory (IBasicExpressionFactory factory)
    {
        this.factory = factory;
    }

    public IBasicExpressionFactory getFactory()
    {
        return this.factory;
    }
}
