/*
* Copyright 2002-2007 the original author or authors.
*
* 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.springmodules.lucene.index.config;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.springmodules.lucene.index.factory.concurrent.LockIndexFactory;
import org.springmodules.lucene.index.support.FSDirectoryFactoryBean;
import org.springmodules.lucene.index.support.RAMDirectoryFactoryBean;
import org.springmodules.lucene.index.support.SimpleIndexFactoryBean;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
* for the <code><lucene:index></code> tag.
*
* @author Thierry Templier
*/
class IndexBeanDefinitionParser extends AbstractLuceneBeanDefinitionParser implements BeanDefinitionParser {
private static final String LOCK = "lock";
private static final String CHANNEL = "channel";
private static final String TARGET_INDEX_FACTORY_ATTRIBUTE = "targetIndexFactory";
public static final String FS_DIRECTORY_ID_PREFIX = "fsDirectory-";
public static final String LOCATION_ATTRIBUTE = "location";
public static final String DIRECTORY_ATTRIBUTE = "directory";
public static final String RAM_DIRECTORY_ID_PREFIX = "ramDirectory-";
public static final String TARGET_INDEX_FACTORY_ID_PREFIX = "target-";
public static final String ID_ATTRIBUTE = "id";
public static final String CREATE_ATTRIBUTE = "create";
public static final String ANALYZER_REF_ATTRIBUTE = "analyzer-ref";
public static final String ANALYZER_ATTRIBUTE = "analyzer";
public static final String CONCURRENT_ATTRIBUTE = "concurrent";
public static final String ANALYZER_ELEMENT = "analyzer";
public static final String BEAN_ELEMENT = "bean";
public static final String TRUE_VALUE = "true";
private boolean isFSIndex(Element element) {
return hasAttributeSet(element, LOCATION_ATTRIBUTE);
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
if( isFSIndex(element) ) {
createFSIndex(element, parserContext);
} else {
createRamIndex(element, parserContext);
}
return null;
}
private boolean mustCreateIndex(Element element) {
boolean create = false;
String createAttr = element.getAttribute(CREATE_ATTRIBUTE);
if( createAttr!=null ) {
createAttr = createAttr.trim();
}
if( createAttr!=null && TRUE_VALUE.equals(createAttr) ) {
create = true;
}
return create;
}
private void configureConcurrentIndexFactory(String id, String concurrent, BeanDefinitionRegistry registry, String idIndexFactory) {
/*if( CHANNEL.equals(concurrent) ) {
RootBeanDefinition concurrentIndexFactoryBeanDefinition = new RootBeanDefinition(
ChannelIndexFactory.class);
concurrentIndexFactoryBeanDefinition.setPropertyValues(new MutablePropertyValues());
concurrentIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(TARGET_INDEX_FACTORY_ATTRIBUTE, new RuntimeBeanReference(idIndexFactory));
registry.registerBeanDefinition(id, concurrentIndexFactoryBeanDefinition);
} else */if( LOCK.equals(concurrent)) {
RootBeanDefinition concurrentIndexFactoryBeanDefinition = new RootBeanDefinition(
LockIndexFactory.class);
concurrentIndexFactoryBeanDefinition.setPropertyValues(new MutablePropertyValues());
concurrentIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(TARGET_INDEX_FACTORY_ATTRIBUTE, new RuntimeBeanReference(idIndexFactory));
registry.registerBeanDefinition(id, concurrentIndexFactoryBeanDefinition);
}
}
private void createRamIndex(Element element, ParserContext parserContext) {
String id = element.getAttribute(ID_ATTRIBUTE);
boolean create = mustCreateIndex(element);
String concurrent = element.getAttribute(CONCURRENT_ATTRIBUTE);
boolean concurrentEnabled = !"".equals(concurrent);
BeanDefinitionRegistry registry = parserContext.getRegistry();
//Definition of the RAM Directory
RootBeanDefinition ramDirectoryBeanDefinition = new RootBeanDefinition(
RAMDirectoryFactoryBean.class);
registry.registerBeanDefinition(RAM_DIRECTORY_ID_PREFIX + id, ramDirectoryBeanDefinition);
//Definition of the index factory
RootBeanDefinition simpleIndexFactoryBeanDefinition = new RootBeanDefinition(
SimpleIndexFactoryBean.class);
simpleIndexFactoryBeanDefinition.setPropertyValues(new MutablePropertyValues());
simpleIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(DIRECTORY_ATTRIBUTE, new RuntimeBeanReference(RAM_DIRECTORY_ID_PREFIX + id));
simpleIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(CREATE_ATTRIBUTE, new Boolean(create));
//Configuration of the analyzer of the factory
configureAnalyzer(element, simpleIndexFactoryBeanDefinition, parserContext);
String idIndexFactory = concurrentEnabled ? TARGET_INDEX_FACTORY_ID_PREFIX + id : id;
registry.registerBeanDefinition(idIndexFactory, simpleIndexFactoryBeanDefinition);
if( concurrentEnabled ) {
configureConcurrentIndexFactory(id, concurrent, registry, idIndexFactory);
}
}
private void createFSIndex(Element element, ParserContext parserContext) {
String id = element.getAttribute(ID_ATTRIBUTE);
String location = element.getAttribute(LOCATION_ATTRIBUTE);
String concurrent = element.getAttribute(CONCURRENT_ATTRIBUTE);
boolean concurrentEnabled = !"".equals(concurrent);
System.out.println("concurrent = "+concurrent);
System.out.println("concurrentEnabled = "+concurrentEnabled);
boolean create = mustCreateIndex(element);
BeanDefinitionRegistry registry = parserContext.getRegistry();
//Definition of the FS Directory
RootBeanDefinition fsDirectoryBeanDefinition = new RootBeanDefinition(
FSDirectoryFactoryBean.class);
fsDirectoryBeanDefinition.setPropertyValues(new MutablePropertyValues());
fsDirectoryBeanDefinition.getPropertyValues()
.addPropertyValue(LOCATION_ATTRIBUTE, location);
registry.registerBeanDefinition(FS_DIRECTORY_ID_PREFIX + id, fsDirectoryBeanDefinition);
//Definition of the index factory
RootBeanDefinition simpleIndexFactoryBeanDefinition = new RootBeanDefinition(
SimpleIndexFactoryBean.class);
simpleIndexFactoryBeanDefinition.setPropertyValues(new MutablePropertyValues());
simpleIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(DIRECTORY_ATTRIBUTE, new RuntimeBeanReference(FS_DIRECTORY_ID_PREFIX + id));
simpleIndexFactoryBeanDefinition.getPropertyValues()
.addPropertyValue(CREATE_ATTRIBUTE, new Boolean(create));
//Configuration of the analyzer of the factory
configureAnalyzer(element, simpleIndexFactoryBeanDefinition, parserContext);
String idIndexFactory = concurrentEnabled ? TARGET_INDEX_FACTORY_ID_PREFIX + id : id;
registry.registerBeanDefinition(idIndexFactory, simpleIndexFactoryBeanDefinition);
if( concurrentEnabled ) {
configureConcurrentIndexFactory(id, concurrent, registry, idIndexFactory);
}
}
private boolean hasAnalyzerRef(Element element) {
return hasAttributeSet(element, ANALYZER_REF_ATTRIBUTE);
}
private void configureAnalyzerRef(MutablePropertyValues propertyValues, String analyzerRef) {
//Compute the bean reference of the analyzer
propertyValues.addPropertyValue(ANALYZER_ATTRIBUTE, new RuntimeBeanReference(analyzerRef));
}
private BeanDefinitionHolder handlerAnalyzerDefinition(Element element, RootBeanDefinition definition, ParserContext parserContext) {
Element beanElement = DomUtils.getChildElementByTagName(element, BEAN_ELEMENT);
if( beanElement!=null ) {
//Compute the inner bean of the analyzer
BeanDefinitionParserDelegate delegate = parserContext.getDelegate();
BeanDefinitionHolder holder = delegate.parseBeanDefinitionElement(beanElement, definition);
if( holder!=null ) {
holder = delegate.decorateBeanDefinitionIfRequired(beanElement, holder);
}
return holder;
}
return null;
}
private void configureInnerAnalyzer(Element element, RootBeanDefinition definition, ParserContext parserContext, MutablePropertyValues propertyValues) {
Element analyzerElement = DomUtils.getChildElementByTagName(element, ANALYZER_ELEMENT);
if( analyzerElement!=null ) {
BeanDefinitionHolder analyzer = handlerAnalyzerDefinition(analyzerElement, definition, parserContext);
if( analyzer!=null ) {
propertyValues.addPropertyValue(ANALYZER_ATTRIBUTE, analyzer);
}
}
}
private void configureAnalyzer(Element element, RootBeanDefinition definition, ParserContext parserContext) {
MutablePropertyValues propertyValues = definition.getPropertyValues();
if( hasAnalyzerRef(element) ) {
String analyzerRef = element.getAttribute(ANALYZER_REF_ATTRIBUTE);
configureAnalyzerRef(propertyValues, analyzerRef);
} else {
configureInnerAnalyzer(element, definition, parserContext, propertyValues);
}
}
}