/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/search/IndexTrigger.java,v 1.3 2004/07/28 09:35:11 ib Exp $
* $Revision: 1.3 $
* $Date: 2004/07/28 09:35:11 $
*
* ====================================================================
*
* Copyright 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.search;
import org.apache.slide.common.Domain;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.event.*;
import org.apache.slide.util.conf.Configurable;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationException;
import org.apache.slide.util.logger.Logger;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
/**
* @version $Revision: 1.3 $
*/
public class IndexTrigger implements EventCollectionListener, Configurable {
protected static final String LOG_CHANNEL = IndexTrigger.class.getName();
protected List indexers = new ArrayList();
public void configure(Configuration configuration) throws ConfigurationException {
Enumeration contentIndexers = configuration.getConfigurations("indexer");
while (contentIndexers.hasMoreElements()) {
Configuration listenerConfig = (Configuration)contentIndexers.nextElement();
String classname = listenerConfig.getAttribute("classname");
String uri = listenerConfig.getAttribute("uri", null);
String contentType = listenerConfig.getAttribute("content-type", null);
boolean synchronous = listenerConfig.getAttributeAsBoolean("synchronous", false);
try {
Class listenerClass = Class.forName(classname);
Indexer indexer = null;
try {
Method getInstanceMethod = listenerClass.getMethod("getInstance", new Class[0]);
indexer = (Indexer)getInstanceMethod.invoke(null, null);
} catch ( NoSuchMethodException e) {
indexer = (Indexer)listenerClass.newInstance();
}
if ( indexer instanceof Configurable ) {
((Configurable)indexer).configure(listenerConfig.getConfiguration("configuration"));
}
addIndexer(indexer, contentType, uri, synchronous);
} catch (ClassCastException e) {
throw new ConfigurationException("Indexer '"+classname+"' is not of type Indexer", configuration);
} catch (Exception e) {
throw new ConfigurationException("Indexer '"+classname+"' could not be loaded", configuration);
}
}
}
public void vetoableCollected(EventCollection collection) throws VetoException {
try {
triggerIndexers(collection, true);
} catch ( IndexException e ) {
throw new VetoException(e.getMessage());
}
}
public void collected(EventCollection collection) {
try {
triggerIndexers(collection, false);
} catch ( IndexException e ) {
Domain.log("Index might be out of sync! Reason: "+e.getMessage(), LOG_CHANNEL, Logger.CRITICAL);
}
}
private synchronized void triggerIndexers(EventCollection collection, boolean synchronous) throws IndexException {
ContentEvent[] update = EventCollectionFilter.getChangedContents(collection);
for ( int i = 0; i < update.length; i++ ) {
Indexer[] indexers = getIndexers(update[i].getRevisionDescriptors(), update[i].getRevisionDescriptor(), synchronous);
for ( int j = 0; j < indexers.length; j++ ) {
indexers[j].updateIndex(new Uri(update[i].getNamespace(), update[i].getUri()), update[i].getRevisionDescriptor(), update[i].getRevisionContent());
}
}
ContentEvent[] insert = EventCollectionFilter.getCreatedContents(collection);
for ( int i = 0; i < insert.length; i++ ) {
Indexer[] indexers = getIndexers(insert[i].getRevisionDescriptors(), insert[i].getRevisionDescriptor(), synchronous);
for ( int j = 0; j < indexers.length; j++ ) {
indexers[j].createIndex(new Uri(insert[i].getNamespace(), insert[i].getUri()), insert[i].getRevisionDescriptor(), insert[i].getRevisionContent());
}
}
ContentEvent[] delete = EventCollectionFilter.getRemovedContents(collection);
for ( int i = 0; i < delete.length; i++ ) {
Indexer[] indexers = getIndexers(delete[i].getRevisionDescriptors(), delete[i].getRevisionDescriptor(), synchronous);
for ( int j = 0; j < indexers.length; j++ ) {
indexers[j].dropIndex(new Uri(delete[i].getNamespace(), delete[i].getUri()), delete[i].getRevisionDescriptor().getRevisionNumber());
}
}
}
private void addIndexer(Indexer indexer, String contentType, String uri, boolean synchronous) {
indexers.add(new IndexerMapping(indexer, contentType, uri, synchronous));
}
private Indexer []getIndexers(NodeRevisionDescriptors descriptors, NodeRevisionDescriptor descriptor, boolean synchronous) {
List matchingIndexers = new ArrayList();
for ( Iterator i = indexers.iterator(); i.hasNext(); ) {
IndexerMapping mapping = (IndexerMapping)i.next();
if ( mapping.isSynchronous() == synchronous && mapping.matches(descriptors, descriptor)) {
matchingIndexers.add(mapping.getIndexer());
}
}
Indexer[] indexers = new Indexer[matchingIndexers.size()];
return (Indexer [])matchingIndexers.toArray(indexers);
};
class IndexerMapping {
Indexer indexer;
String uri, contentType;
boolean synchronous;
public IndexerMapping(Indexer indexer, String contentType, String uri, boolean synchronous) {
this.indexer = indexer;
this.uri = uri;
this.contentType = contentType;
this.synchronous = synchronous;
}
public Indexer getIndexer() {
return indexer;
}
public boolean isSynchronous() {
return synchronous;
}
public boolean matches(NodeRevisionDescriptors descriptors, NodeRevisionDescriptor descriptor) {
boolean matching = true;
if ( descriptor != null && contentType != null && !descriptor.getContentType().equals(contentType) ) {
matching = false;
}
if ( descriptors != null && uri != null && !descriptors.getUri().startsWith(uri) ) {
matching = false;
}
return matching;
}
}
}