/*
SDX: Documentary System in XML.
Copyright (C) 2000  Ministere de la culture et de la communication (France), AJLSM

Ministere de la culture et de la communication,
Mission de la recherche et de la technologie
3 rue de Valois, 75042 Paris Cedex 01 (France)
mrt@culture.fr, michel.bottin@culture.fr

AJLSM, 17, rue Vital Carles, 33000 Bordeaux (France)
sevigny@ajlsm.com

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

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
or connect to:
http://www.fsf.org/copyleft/gpl.html
 */
package fr.gouv.culture.sdx.search.lucene.query;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.framework.Framework;
import fr.gouv.culture.sdx.search.lucene.Field;
import fr.gouv.culture.sdx.utils.constants.Node;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.TermQuery;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/*	Contient une requete exacte sur un terme dans un champ.
 *
 *	Aucune traitement n'est effectue sur cette requete. Pour effectuer
 *	une recherche sur un terme dans un champ, de facon generale, il
 *	est preferable d'utiliser la classe FieldQuery, qui tient compte
 *	du type de champ dont il s'agit.
 */

/**
 * Contains an exact acceptRequest on a term in a field.
 *
 * No treatment is carried out on this acceptRequest.
 * To carry out a research on a term in a field,
 * in a general way, it is preferable to use the FieldQuery class,
 * which takes account of the type of field.
 */
public class ExactFieldQuery extends AbstractQuery {

    /** The given query string. */
//	FIXME : private field never used locally [MP]
    private String queryText;

    /** The field used. */
    private Field field;

    /**Creates a query
     *
     *  <p>
     * A super.getLog() must be set and then this query must be setUp.
     *
     * @see #enableLogging
     * @see #setUp
     */
    public ExactFieldQuery() {
    }

    /**
     *	Builds an exact field query.
     *
     *@param	sLocs       The SearchLocationsindex to be searched.
     *@param	fieldName	The field to search (if null or non existant, the default field will be searched).
     *@param	q		    The query string.
     *@throws SDXException
     */
    public void setUp(SearchLocations sLocs, String fieldName, String q) throws SDXException {

        super.setSearchLocations(sLocs);

        if (q == null) throw new SDXException(null, SDXExceptionCode.ERROR_QUERY_NULL, null, null);

        this.field = searchLocations.getField(fieldName);
        if (this.field == null) this.field = sLocs.getDefaultField();

        if (this.field == null) {
            String[] args = new String[1];
            args[0] = fieldName;
            throw new SDXException(super.getLog(), SDXExceptionCode.ERROR_FIELD_DOES_NOT_EXIST, args, null);
        }

        // The query string
        queryText = q;

        // Builds a Lucene term query
        luceneQuery = new TermQuery(new Term(field.getCode(), q));
    }

    /**
     *	Retourne une representation DOM de cette requete.
     *
     *	@param	factory		Le document DOM servant de manufacture.
     */
/*
	public Element toDOM(Document factory) throws SDXException
	{
		if ( queryElement == null )
		{
			String nsURI = Framework.SDXNamespaceURI;
			String nsPrefix = Framework.SDXNamespacePrefix;

			// On doit la construire
			queryElement = factory.createElementNS(nsURI, nsPrefix + ":query");
			queryElement.setAttribute("xmlns:" + nsPrefix, nsURI);
			queryElement.setAttribute("type", "exactField");
			queryElement.setAttribute("luceneQuery", luceneQuery.toString(db.toString()));
//			Element term = factory.createElementNS(nsURI, nsPrefix + ":term");
//			term.setAttribute("defaultField", dbInfo.getDefaultField());
			queryElement.setAttribute("field", fieldName);
//			queryElement.appendChild(term);
			queryElement.setAttribute("text", queryText);

			//Then add the search locations
			this.getSearchLocations().toSAX(hdl);

			// On ajoute les filtres
			if ( filter != null ) queryElement.appendChild(filter.toDOM(factory));

			// On ajoute la requete de base
			if ( baseQuery != null )
			{
				Element baseQueryEl = factory.createElementNS(Utilities.getSDXNamespaceURI(), Utilities.getSDXNamespacePrefix() + ":baseQuery");
				baseQueryEl.setAttribute("xmlns:" + Utilities.getSDXNamespacePrefix(), Utilities.getSDXNamespaceURI());
				baseQueryEl.appendChild(baseQuery.toDOM(factory));
				queryElement.appendChild(baseQueryEl);
			}

			return queryElement;
		}
		else
		{
			// On l'a deja, on l'importe
			return (Element)factory.importNode(queryElement, true);
		}
	}

 */
    /**
     * Formats a query in XML.
     *
     *@param   hdl     A content handler to receive XML data.
     *@throws SAXException
     */
    public void toSAX(ContentHandler hdl) throws SAXException {
        String sdxNsUri = Framework.SDXNamespaceURI;
        String sdxNsPrefix = Framework.SDXNamespacePrefix;
        String localName = Node.Name.QUERY;
        String qName = sdxNsPrefix + ":" + localName;
        AttributesImpl atts = new AttributesImpl();
        atts.addAttribute("", Node.Name.TYPE, Node.Name.TYPE, Node.Type.CDATA, "exactField");
        atts = super.addAttributesLucene(atts);
        atts = super.addAttributesText(atts);
        atts.addAttribute("", Node.Name.FIELD, Node.Name.FIELD, Node.Type.CDATA, field.getCode());
        //Let's build the query representation
        hdl.startElement(sdxNsUri, localName, qName, atts);

        //Then add the search locations
        this.getSearchLocations().toSAX(hdl);

        //Then add the filter
        if (filter != null) filter.toSAX(hdl);

        //Then add the base query
        if (baseQuery != null) {
            String bqLocalName = Node.Name.BASE_QUERY;
            String bqQName = sdxNsPrefix + ":" + bqLocalName;
            AttributesImpl emptyAtts = new AttributesImpl();
            hdl.startElement(sdxNsUri, bqLocalName, bqQName, emptyAtts);
            baseQuery.toSAX(hdl);
            hdl.endElement(sdxNsUri, bqLocalName, bqQName);

        }

        //All over
        hdl.endElement(sdxNsUri, localName, qName);

    }

}
