/*
 * $Header: /home/cvspublic/jakarta-slide/src/stores/org/apache/slide/index/lucene/LuceneContentIndexer.java,v 1.3 2005/04/04 13:55:13 luetzkendorf Exp $
 * $Revision: 1.3 $
 * $Date: 2005/04/04 13:55:13 $
 *
 * ====================================================================
 *
 * Copyright 1999-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.lucene;

import java.io.ByteArrayInputStream;
import java.util.Hashtable;

import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;

import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.ServiceInitializationFailedException;
import org.apache.slide.common.ServiceParameterErrorException;
import org.apache.slide.common.ServiceParameterMissingException;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.event.DomainEvent;
import org.apache.slide.event.EventDispatcher;
import org.apache.slide.extractor.ExtractorManager;
import org.apache.slide.search.IndexException;


/**
 * IndexStore implementation for indexing content based on Jakarta Lucene.
 */
public class LuceneContentIndexer extends AbstractLuceneIndexer
{
    private static final String ANALYZER_PARAM = "analyzer";
    private String analyzerClassName;
    
    public void initialize(NamespaceAccessToken token)
            throws ServiceInitializationFailedException
    {
        super.initialize(token);
        try {
            indexConfiguration.initDefaultConfiguration();
            
            indexConfiguration.setContentAnalyzer(
                    createAnalyzer(this.analyzerClassName));
            
            this.index = new Index(indexConfiguration, getLogger(), 
                    "content " + this.scope);
            
            if (this.index.needsInitialization()) {
            	DomainEvent.NAMESPACE_INITIALIZED.setEnabled(true);
            	EventDispatcher.getInstance().addEventListener(
            			new IndexInitializer(this.scope, IndexInitializer.CONTENT, getLogger()));
            }
        } 
        catch (IndexException e) {
            throw new ServiceInitializationFailedException(this, e);
        }
    }
    
    
    
    
    public void setParameters(Hashtable parameters)
        throws ServiceParameterErrorException,
               ServiceParameterMissingException
    {
        super.setParameters(parameters);
        analyzerClassName = (String)parameters.get(ANALYZER_PARAM);
    }

    /**
     * This implementation just calls the super implementation and catches
     * all exceptions to ensure that content indexing never makes a commit failing.
     */
    public void commit(Xid xid, boolean onePhase) throws XAException
    {
        try {
            super.commit(xid, onePhase);
        } catch (XAException e) {
            error("Error while committing to content index ({0})", e);
        }
    }

    /* 
     * @see org.apache.slide.search.Indexer#createIndex(org.apache.slide.common.Uri, org.apache.slide.content.NodeRevisionDescriptor, org.apache.slide.content.NodeRevisionContent)
     */
    public void createIndex(Uri uri, NodeRevisionDescriptor revisionDescriptor,
            NodeRevisionContent revisionContent) throws IndexException
    {
        if (isIncluded(uri.toString())) {
            if (ExtractorManager.getInstance().hasContentExtractor(
                    uri.getNamespace().getName(), uri.toString(), revisionDescriptor)) 
            {
                TransactionalIndexResource indexResource = getCurrentTxn();
                indexResource.addIndexJob(uri, revisionDescriptor, 
                        new ByteArrayInputStream(revisionContent.getContentBytes()));
            }
        }
    }


    /* 
     * @see org.apache.slide.search.Indexer#updateIndex(org.apache.slide.common.Uri, org.apache.slide.content.NodeRevisionDescriptor, org.apache.slide.content.NodeRevisionContent)
     */
    public void updateIndex(Uri uri, NodeRevisionDescriptor revisionDescriptor,
            NodeRevisionContent revisionContent) throws IndexException
    {
        if (isIncluded(uri.toString())) {
            if (ExtractorManager.getInstance().hasContentExtractor(
                    uri.getNamespace().getName(), uri.toString(), revisionDescriptor)) 
            {
                TransactionalIndexResource indexResource = getCurrentTxn();
                indexResource.addUpdateJob(uri, revisionDescriptor, 
                        new ByteArrayInputStream(revisionContent.getContentBytes()));
            }
        }
    }
    
    /* 
     * @see org.apache.slide.search.Indexer#dropIndex(org.apache.slide.common.Uri, org.apache.slide.content.NodeRevisionNumber)
     */
    public void dropIndex(Uri uri, NodeRevisionNumber number)
            throws IndexException
    {
        if (isIncluded(uri.toString())) {
            if (ExtractorManager.getInstance().hasContentExtractor(
                    uri.getNamespace().getName(), uri.toString(), null)) 
            {
                TransactionalIndexResource indexResource = getCurrentTxn();
                indexResource.addRemoveJob(uri, number);
            }
        }

    }

    protected Analyzer createAnalyzer(String clsName) 
        throws ServiceInitializationFailedException 
    {
        Analyzer analyzer;
        if (clsName == null || clsName.length() == 0) {
            analyzer = new SimpleAnalyzer();

        } else {

            try {
                Class analyzerClazz = Class.forName(clsName);
                analyzer = (Analyzer)analyzerClazz.newInstance();

            } catch (ClassNotFoundException e) {
                error("Error while instantiating analyzer {1} {2}", 
                                clsName, e.getMessage());
                throw new ServiceInitializationFailedException(this, e);

            } catch (InstantiationException e) {
                error("Error while instantiating analyzer {1} {2}", 
                        clsName, e.getMessage());
                throw new ServiceInitializationFailedException(this, e);

            } catch (IllegalAccessException e) {
                error("Error while instantiating analyzer {1} {2}", 
                        clsName, e.getMessage());
                throw new ServiceInitializationFailedException(this, e);
            }
        }
        
        info("using analyzer: {0}", analyzer.getClass().getName());
        return analyzer;
    }
}
