/*
 * $Header: /home/cvspublic/jakarta-slide/src/stores/org/apache/slide/index/lucene/IndexInitializer.java,v 1.1 2005/03/29 08:08:00 luetzkendorf Exp $
 * $Revision: 1.1 $
 * $Date: 2005/03/29 08:08:00 $
 *
 * ====================================================================
 *
 * 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.util.Enumeration;

import org.apache.slide.authenticate.CredentialsToken;
import org.apache.slide.authenticate.SecurityToken;
import org.apache.slide.common.Domain;
import org.apache.slide.common.Namespace;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.Scope;
import org.apache.slide.common.SlideToken;
import org.apache.slide.common.SlideTokenImpl;
import org.apache.slide.common.SlideTokenWrapper;
import org.apache.slide.common.Uri;
import org.apache.slide.content.Content;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionContentNotFoundException;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.event.DomainAdapter;
import org.apache.slide.event.DomainEvent;
import org.apache.slide.search.IndexException;
import org.apache.slide.store.AbstractStore;
import org.apache.slide.store.Store;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.StructureIterator;
import org.apache.slide.util.logger.Logger;


/**
 * Initializer used to index all existing documents in a store. This is 
 * created and registered as en event listener by {@link LucenePropertiesIndexer} 
 * or {@link LuceneContentIndexer} if there is existing index so we are 
 * sure that all documents are to be to be indexed. 
 */
public class IndexInitializer extends DomainAdapter
{
	static final int CONTENT = 1;
	static final int PROPERTIES = 2;
	private Scope scope;
	private int indexType;
	private Logger logger;
	
	
	IndexInitializer(Scope scope, int indexType, Logger logger) {
		this.scope = scope;
		this.indexType = indexType;
		this.logger = logger;
	}

    public void namespaceInitialized(DomainEvent event)
    {
        Namespace namespace = event.getNamespace();

        NamespaceAccessToken nsa = Domain.accessNamespace(new SecurityToken(""), 
        		namespace.getName());
        
        Content content = nsa.getContentHelper();
        Store indexedStore = namespace.getStore(this.scope);
        
        SlideToken slideToken = new SlideTokenImpl(new CredentialsToken(""));
        slideToken = new SlideTokenWrapper(slideToken);
        slideToken.setForceStoreEnlistment(true);
        slideToken.setForceSecurity(false);
        String logChannel = getClass().getName();

        try {
            nsa.begin();
            StructureIterator i = new StructureIterator(nsa.getStructureHelper(),
                    slideToken, this.scope.toString());
            
            logger.log("Init " + (indexType == CONTENT ? "content" : "properties" ) 
            		+ " index for scope " + this.scope, logChannel, Logger.INFO);
            
            while (i.hasNext()) {
                ObjectNode node = i.nextNode();
                
                NodeRevisionDescriptors nrds = content.retrieve(slideToken, node.getUri());
                for(Enumeration e = nrds.enumerateRevisionNumbers(); e.hasMoreElements();) {
                	Uri uri = nsa.getUri(slideToken, node.getUri());
                	Store store = uri.getStore();
                	NodeRevisionNumber nrn = (NodeRevisionNumber)e.nextElement();
                	
                	if(store == indexedStore && store instanceof AbstractStore) {
                    	NodeRevisionDescriptor nrd = null;
	                	
						try {
		                	nrd = content.retrieve(slideToken, nrds, nrn);
		                	if (indexType == PROPERTIES) {
		                		((AbstractStore)store).createPropertiesIndex(uri, nrd, null);
		                		logger.log(node.getUri() + " props: " + nrn, logChannel, Logger.DEBUG);
		                	}
	                    } catch (RevisionDescriptorNotFoundException ex) {
							continue;
	                	} catch(IndexException ex) {
	                        logger.log("Error while initalizing properties index for " 
	                        		+ uri + " (" + nrn + ")", ex, logChannel, Logger.ERROR);
	                	} 
	                	
	                	try {
	                		if (indexType == CONTENT) {
		                		NodeRevisionContent nrc = content.retrieve(slideToken, nrds, nrd);
		                		((AbstractStore)store).createContentIndex(uri, nrd, nrc);
		                		logger.log(node.getUri() + " content: " + nrn, logChannel, Logger.DEBUG);
	                		}
	                	} catch (RevisionNotFoundException ex) { 
	                		// ignore no content?
	                	} catch (RevisionContentNotFoundException ex) {
	                		// ignore not content
	                	} catch (IndexException ex) {
	                		logger.log("Error while initalizing content index for " 
	                        		+ uri + " (" + nrn + ")", ex, logChannel, Logger.ERROR);
	                	} 
                	}
                }
            }
            
            logger.log("Init " + (indexType == CONTENT ? "content" : "properties" ) 
            		+ " index for scope " + this.scope + " done", logChannel, Logger.INFO);
            
        } catch (Exception e) {
            Domain.error("Error while initializing " + 
            		(indexType == CONTENT ? "content" : "properties" )+ " index for scope " + 
					this.scope, e);
        } finally {
            try {
                nsa.commit();
            } catch (Exception e) {
                Domain.error("Error while commiting initialized " + 
                		(indexType == CONTENT ? "content" : "properties" )+ " index for scope " + 
    					this.scope, e);
            }
        }
        
    }
}
