/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/
package fr.gouv.culture.sdx.utils.lucene;

import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.utils.AbstractSdxObject;
import fr.gouv.culture.sdx.utils.Utilities;

/**In progress, good idea, but we need a use case?-rbp
 *
 * This class basically provides an easy way to build a lucene document
 * for store in a LuceneDataStore
 * Created by IntelliJ IDEA.
 * User: rpandey
 * Date: Dec 12, 2002
 * Time: 2:14:55 PM
 * To change this template use Options | File Templates.
 */
public class LuceneData extends AbstractSdxObject {

    public static final String CLASS_NAME_SUFFIX = "LuceneData";
    protected Hashtable ldFields = new Hashtable();
    public final static String allKey = LuceneDataStore.ALL_FIELD;
    public final static String allValue = LuceneDataStore.ALL_VALUE;
    public final static String idKey = LuceneDataStore.ID_FIELD;
    public final static String xmlLangKey = LuceneDataStore.XML_LANG_FIELD;

    public LuceneData() {
        addLDField(allKey, allValue);
    }


    public LuceneData(Document lDoc) {
        if (lDoc != null) {
            Enumeration lFields = lDoc.fields();
            if (lFields != null) {
                while (lFields.hasMoreElements()) {
                    Field field = (Field) lFields.nextElement();
                    if (field != null)
                        addLDField(field);
                }
            }
        }
    }

    public void setId(String id) {
        addLDField(idKey, id);
    }

    public void setXmlLang(String xmlLang) {
        addLDField(xmlLangKey, xmlLang);
    }

    public String getXmlLang() {

        /*if one is building a LuceneData object we return
        *the value from our internal data structures
        */
        LuceneDataField xmlLang = getField(xmlLangKey);
        if (xmlLang != null)
            return xmlLang.getValue();
        else
            return null;

    }

    public String getId() {
        /*if one is building a LuceneData object we return
        *the value from our internal data structures
        */
        LuceneDataField id = getField(idKey);
        if (id != null)
            return id.getValue();
        else
            return null;
    }

    public void addField(String fieldName, String value, String type) {
        if (Utilities.checkString(fieldName)) {
            if (ldFields.containsKey(fieldName))
                updateLDField(fieldName, value);
            else
                addLDField(fieldName, value, type);
        }
    }

    public void removeField(String fieldName) {
        deleteLDField(fieldName);
    }

    public void removeValue(String fieldName, String value) {
        if (ldFields.containsKey(fieldName)) {
            if (Utilities.checkString(value)) {
                LuceneDataField ldf = getField(fieldName);
                if (ldf != null)
                    ldf.deleteValue(value);
            }
        }
    }

    public String[] getFieldValues(String fieldName) {
        if (Utilities.checkString(fieldName)) {
            if (ldFields.containsKey(fieldName)) {
                LuceneDataField ldf = getField(fieldName);
                if (ldf != null)
                    return ldf.getValues();
                else
                    return null;
            } else
                return null;
        } else
            return null;
    }

    public String getFieldValue(String fieldName) {
        if (Utilities.checkString(fieldName)) {
            if (ldFields.containsKey(fieldName)) {
                LuceneDataField ldf = getField(fieldName);
                if (ldf != null)
                    return ldf.getValue();
                else
                    return null;
            } else
                return null;

        } else
            return null;
    }


    /**
     * Returns a Lucene f based upon the current set of properties/LuceneDataFields.
     *
     */
    public Document getLuceneDocument() {
        Document ldoc = null;
        // Now the properties
        Enumeration props = ldFields.elements();
        if (props != null) {
            ldoc = new Document();
            while (props.hasMoreElements()) {
                LuceneDataField ldf = (LuceneDataField) props.nextElement();
                if (ldf != null) {
                    String[] values = ldf.getValues();
                    for (int j = 0; j < values.length; j++) {
                        ldoc.add(ldf.getLuceneField(values[j]));
                    }
                }
            }
        }
        return ldoc;

    }

    /**Builds a keyworld lucene field*/
    protected void addLDField(String name, String value) {
        if (Utilities.checkString(name) && Utilities.checkString(value)) {
            LuceneDataField ldf = new LuceneDataField();
            ldf.setName(name);
            ldf.setFieldType(true, true, false);
            ldf.addValue(value);
            ldFields.put(name, ldf);
        }
    }

    protected void addLDField(String name, String value, String type) {
        if (Utilities.checkString(name) && Utilities.checkString(value)) {
            LuceneDataField ldf = new LuceneDataField();
            ldf.setName(name);
            ldf.setFieldType(type);
            ldf.addValue(value);
            ldFields.put(name, ldf);
        }
    }

    protected void addLDField(Field f) {
        String name = "";
        String value = "";
        boolean store = false;
        boolean index = false;
        boolean token = false;
        if (f != null) {
            name = f.name();
            value = f.stringValue();
            store = f.isStored();
            index = f.isIndexed();
            token = f.isTokenized();
        }

        if (Utilities.checkString(name) && Utilities.checkString(value)) {
            LuceneDataField ldf = new LuceneDataField();
            //ldf.setName(name);
            ldf.setFieldType(store, index, token);
            //ldf.addValue(value);
            addField(name, value, ldf.getTypeName());
            //ldFields.put(name, ldf);
        }
    }

    protected void updateLDField(String name, String value) {
        if (Utilities.checkString(name) && Utilities.checkString(value)) {
            LuceneDataField prop = getField(name);
            if (prop != null)
                prop.addValue(value);
        }

    }

    protected void deleteLDField(String name) {
        if (Utilities.checkString(name) && ldFields.containsKey(name)) {
            ldFields.remove(name);
        }
    }


    /**Gets a specific LuceneDataField*/
    public LuceneDataField getField(String key) {
        LuceneDataField ldf = null;
        if (ldFields.containsKey(key))
            ldf = (LuceneDataField) ldFields.get(key);
        return ldf;
    }

    /**Returns all LuceneDataFields*/
    public Enumeration getFields() {
        return ldFields.elements();
    }

    /**Returns only the content LuceneDataFields, excluding the all, id, and xmllang fields*/
    public Enumeration getContentFields() {
        Hashtable contentFields = new Hashtable(ldFields);
        contentFields.remove(allKey);
        contentFields.remove(idKey);
        contentFields.remove(xmlLangKey);
        return contentFields.elements();
    }

    /**
     * Returns a Lucene field for indexing a name/value pair.
     *
     * @param name      Name of the field.
     * @param value     Value of the field.
     */
    protected Field getLuceneField(String name, String value) throws SDXException {
        //TODO?:not testing the value for an empty string because fred thinks i could be useful?-rbp
        if (!Utilities.checkString(name) || value == null) {
            String[] args = new String[2];
            args[0] = name;
            args[1] = value;
            //not logging here
            throw new SDXException(null, SDXExceptionCode.ERROR_CREATE_LUCENE_FIELD, args, null);
        } else
        	// MAJ Lucene 2.1.0
            //return Field.Keyword(name, value);
        	return new Field(name, value, Field.Store.YES, Field.Index.UN_TOKENIZED);
    }

    protected String getClassNameSuffix() {
        return LuceneData.CLASS_NAME_SUFFIX;
    }


	/* (non-Javadoc)
	 * @see fr.gouv.culture.sdx.utils.AbstractSdxObject#initToSax()
	 */
	protected boolean initToSax() {
		return true;
	}


	/**Init the LinkedHashMap _xmlizable_volatile_objects with the objects in order to describ them in XML
	 * Some objects need to be refresh each time a toSAX is called*/
	protected void initVolatileObjectsToSax() {
	
	}


}
