/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/search/SearchImpl.java,v 1.21 2004/12/15 16:30:18 masonjm Exp $
 * $Revision: 1.21 $
 * $Date: 2004/12/15 16:30:18 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 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.search;

import java.util.HashMap;
import java.util.Map;

import org.apache.slide.common.Namespace;
import org.apache.slide.common.NamespaceConfig;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.content.Content;
import org.apache.slide.search.basic.BasicSearchLanguage;
import org.apache.slide.structure.Structure;
import org.apache.slide.event.VetoException;
import org.apache.slide.event.EventDispatcher;
import org.apache.slide.event.SearchEvent;
import org.jdom.Element;

/**
 * Search helper.
 *
 * @version $Revision: 1.21 $
 */
public class SearchImpl implements Search {
    
    // ----------------------------------------------------------- Constructors
    
    
    /**
     * Constructor.
     *
     * @param namespace Namespace
     * @param namespaceConfig Namespace configuration
     */
    public SearchImpl(Namespace namespace,
                      NamespaceConfig namespaceConfig,
                      Structure structureHelper,
                      Content contentHelper) {
        this.namespace = namespace;
        this.structureHelper = structureHelper;
        this.contentHelper = contentHelper;
    }
    
    
    // ----------------------------------------------------- Instance Variables
    
    // TODO: must be configurable in domain.xml (Namespace.java)
    private static final SearchLanguage [] SEARCH_LANGUAGES = {
        new BasicSearchLanguage ()
    };
    
    
    private static final Map GRAMMAR_BY_URI = new HashMap ();
    static {
        for (int i = 0; i < SEARCH_LANGUAGES.length; i++)
            GRAMMAR_BY_URI.put (SEARCH_LANGUAGES [i].getGrammarUri(),
                                SEARCH_LANGUAGES [i]);
    }
    
    
    /**
     * Namespace.
     */
    private Namespace namespace;
    
    /**
     * Structure.
     */
    private Structure structureHelper;
    
    
    /**
     * Namespace configuration.
     */
    private Content contentHelper;
    
    
    // ------------------------------------------------------- Security Methods
    
    
    /**
     * Search.
     *
     * @param token Credentials token
     * @param query The query to execute
     * @exception ServiceAccessException DataSource access error
     */
    public SearchQueryResult search (SlideToken token, SearchQuery query)
        throws ServiceAccessException, VetoException {

        // Fire event
        if ( SearchEvent.SEARCH.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(SearchEvent.SEARCH, new SearchEvent(this, token, namespace, query));

        return query.execute ();
    }
    
    
    /**
     * Return the allowed query languages.
     */
    public SearchLanguage[] getSupportedLanguages () {
        return SEARCH_LANGUAGES;
    }
    
    
    /**
     * Retrieve a SearchLanguage identified by the grammar uri (namespace)
     *
     * @param    grammarUri          identifier for the SearchLanguage
     *
     * @return   the SearchLanguage
     *
     * @throws   BadQueryException
     *
     */
    public SearchLanguage getLanguage (String grammarUri)
        throws BadQueryException
    {
        SearchLanguage result =(SearchLanguage) GRAMMAR_BY_URI.get (grammarUri);
        if (result == null)
            throw new BadQueryException ("grammar not found: " + grammarUri);
        
        return result;
    }
    
    
    
    
    /**
     * Creates a SearchQuery.
     *
     * @param    grammarUri          identifier for the SearchLanguage
     * @param    queryElement        the JDOM element containing the query
     * @param    token               the SlideToken
     * @param    maxDepth            may be 0, 1 or INFINIT
     *
     * @return   the SearchQuery
     *
     * @throws   BadQueryException
     *
     */
    public SearchQuery createSearchQuery (String grammarUri,
                                       Element queryElement,
                                       SlideToken token,
                                       int maxDepth)
        throws BadQueryException
    {
        return createSearchQuery (grammarUri, queryElement, token, maxDepth, (PropertyProvider)null);
    }
    
    /**
     * Creates a SearchQuery.
     *
     * @param    grammarUri            identifier for the SearchLanguage.
     * @param    searchRequestElement  the JDOM element containing the query
     * @param    token                 the SlideToken.
     * @param    maxDepth              may be 0, 1 or INFINITY.
     * @param    propertyProvider      the  PropertyProvider to use (may be
     *                                 <code>null</code>).
     *
     * @return   the SearchQuery
     *
     * @throws   BadQueryException
     */
    public SearchQuery createSearchQuery (String grammarUri,
                                   Element searchRequestElement,
                                   SlideToken token,
                                   int maxDepth,
                                   PropertyProvider propertyProvider)
        throws BadQueryException
    {
        return createSearchQuery (grammarUri, searchRequestElement, token, maxDepth, propertyProvider, null);
    }
    
    /**
     * Creates a SearchQuery.
     *
     * @param    grammarUri          identifier for the SearchLanguage
     * @param    queryElement        the JDOM element containing the query
     * @param    token               the SlideToken
     * @param    maxDepth            may be 0, 1 or INFINIT
     *
     * @return   the SearchQuery
     *
     * @throws   BadQueryException
     *
     */
    public SearchQuery createSearchQuery (String grammarUri,
                                          Element queryElement,
                                          SlideToken token,
                                          int maxDepth,
                                          String requestUri)
        throws BadQueryException
    {
        return createSearchQuery (grammarUri, queryElement, token, maxDepth, null, requestUri);
    }

    /**
     * Creates a SearchQuery.
     *
     * @param    grammarUri            identifier for the SearchLanguage.
     * @param    searchRequestElement  the JDOM element containing the query
     * @param    token                 the SlideToken.
     * @param    maxDepth              may be 0, 1 or INFINITY.
     * @param    propertyProvider      the  PropertyProvider to use (may be
     *                                 <code>null</code>).
     * @param    requestUri            the  URI of the request.
     *
     * @return   the SearchQuery
     *
     * @throws   BadQueryException
     */
    public SearchQuery createSearchQuery (String grammarUri,
                                   Element searchRequestElement,
                                   SlideToken token,
                                   int maxDepth,
                                   PropertyProvider propertyProvider,
                                   String requestUri)
        throws BadQueryException
    {
        SearchQuery result = null;
        // create search token
        SearchToken searchToken =
            SearchToken.createSearchToken (token, contentHelper,
                                           structureHelper, maxDepth,
                                           requestUri, namespace);
        
        SearchLanguage language = getLanguage (grammarUri);
        result = language.parseQuery (searchRequestElement, searchToken, propertyProvider);
    
        return result;
    }
}

