/*
* Copyright 2004-2014 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.springframework.faces.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for the flow-builder-services tag.
*
* @author Jeremy Grelle
* @author Christian Dupuis
*/
public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements
BeanDefinitionParser {
// --------------------------- Full qualified class names ----------------------- //
private static final String FACES_CONVERSION_SERVICE_CLASS_NAME = "org.springframework.faces.model.converter.FacesConversionService";
private static final String FLOW_BUILDER_SERVICES_CLASS_NAME = "org.springframework.webflow.engine.builder.support.FlowBuilderServices";
private static final String JSF_VIEW_FACTORY_CREATOR_CLASS_NAME = "org.springframework.faces.webflow.JsfViewFactoryCreator";
private static final String FACES_SPRING_EL_EXPRESSION_PARSER_CLASS_NAME = "org.springframework.faces.webflow.FacesSpringELExpressionParser";
private static final String WEBFLOW_SPRING_EL_EXPRESSION_PARSER_CLASS_NAME = "org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser";
// --------------------------- XML Config Attributes ----------------------- //
private static final String CONVERSION_SERVICE_ATTR = "conversion-service";
private static final String DEVELOPMENT_ATTR = "development";
private static final String ENABLE_MANAGED_BEANS_ATTR = "enable-managed-beans";
private static final String EXPRESSION_PARSER_ATTR = "expression-parser";
private static final String VIEW_FACTORY_CREATOR_ATTR = "view-factory-creator";
private static final String VALIDATOR_ATTR = "validator";
private static final String VALIDATION_HINT_RESOLVER_ATTR = "validation-hint-resolver";
// --------------------------- Bean Configuration Properties --------------------- //
private static final String CONVERSION_SERVICE_PROPERTY = "conversionService";
private static final String DEVELOPMENT_PROPERTY = "development";
private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser";
private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator";
private static final String VALIDATOR_PROPERTY = "validator";
private static final String VALIDATION_HINT_RESOLVER_PROPERTY = "validationHintResolver";
protected String getBeanClassName(Element element) {
return FLOW_BUILDER_SERVICES_CLASS_NAME;
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) {
CompositeComponentDefinition componentDefinition = new CompositeComponentDefinition(element.getLocalName(),
parserContext.extractSource(element));
parserContext.pushContainingComponent(componentDefinition);
parseConversionService(element, parserContext, definitionBuilder);
parseExpressionParser(element, parserContext, definitionBuilder,
parseEnableManagedBeans(element, definitionBuilder));
parseViewFactoryCreator(element, parserContext, definitionBuilder);
parseValidator(element, parserContext, definitionBuilder);
parseValidationHintResolver(element, parserContext, definitionBuilder);
parseDevelopment(element, definitionBuilder);
parserContext.popAndRegisterContainingComponent();
}
private boolean parseEnableManagedBeans(Element element, BeanDefinitionBuilder definitionBuilder) {
String enableManagedBeans = element.getAttribute(ENABLE_MANAGED_BEANS_ATTR);
if (StringUtils.hasText(enableManagedBeans)) {
return Boolean.valueOf(enableManagedBeans);
} else {
return false;
}
}
private void parseConversionService(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
String conversionService = element.getAttribute(CONVERSION_SERVICE_ATTR);
if (!StringUtils.hasText(conversionService)) {
BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder
.genericBeanDefinition(FACES_CONVERSION_SERVICE_CLASS_NAME);
conversionService = registerInfrastructureComponent(element, context, conversionServiceBuilder);
}
definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService);
}
private void parseViewFactoryCreator(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTR);
if (!StringUtils.hasText(viewFactoryCreator)) {
BeanDefinitionBuilder viewFactoryCreatorBuilder = BeanDefinitionBuilder
.genericBeanDefinition(JSF_VIEW_FACTORY_CREATOR_CLASS_NAME);
viewFactoryCreator = registerInfrastructureComponent(element, context, viewFactoryCreatorBuilder);
}
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator);
}
private void parseValidator(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
String validator = element.getAttribute(VALIDATOR_ATTR);
if (StringUtils.hasText(validator)) {
definitionBuilder.addPropertyReference(VALIDATOR_PROPERTY, validator);
}
}
private void parseValidationHintResolver(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
String resolver = element.getAttribute(VALIDATION_HINT_RESOLVER_ATTR);
if (StringUtils.hasText(resolver)) {
definitionBuilder.addPropertyReference(VALIDATION_HINT_RESOLVER_PROPERTY, resolver);
}
}
private void parseExpressionParser(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder,
boolean enableManagedBeans) {
// String conversionService = getConversionService(definitionBuilder);
String expressionParser = element.getAttribute(EXPRESSION_PARSER_ATTR);
if (!StringUtils.hasText(expressionParser)) {
BeanDefinitionBuilder spelExpressionParser = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.expression.spel.standard.SpelExpressionParser");
BeanDefinitionBuilder expressionParserBuilder;
if (enableManagedBeans) {
expressionParserBuilder = BeanDefinitionBuilder
.genericBeanDefinition(FACES_SPRING_EL_EXPRESSION_PARSER_CLASS_NAME);
} else {
expressionParserBuilder = BeanDefinitionBuilder
.genericBeanDefinition(WEBFLOW_SPRING_EL_EXPRESSION_PARSER_CLASS_NAME);
}
expressionParserBuilder.addConstructorArgValue(spelExpressionParser.getBeanDefinition());
expressionParserBuilder.addConstructorArgReference(getConversionService(definitionBuilder));
expressionParser = registerInfrastructureComponent(element, context, expressionParserBuilder);
} else if (enableManagedBeans) {
context.getReaderContext().error(
"Do not specify a custom expression-parser when enable-managed-beans is true",
context.extractSource(element));
}
definitionBuilder.addPropertyReference(EXPRESSION_PARSER_PROPERTY, expressionParser);
}
private void parseDevelopment(Element element, BeanDefinitionBuilder definitionBuilder) {
String development = element.getAttribute(DEVELOPMENT_ATTR);
if (StringUtils.hasText(development)) {
definitionBuilder.addPropertyValue(DEVELOPMENT_PROPERTY, development);
}
}
private String getConversionService(BeanDefinitionBuilder definitionBuilder) {
RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition()
.getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue();
return conversionServiceReference.getBeanName();
}
private String registerInfrastructureComponent(Element element, ParserContext context,
BeanDefinitionBuilder componentBuilder) {
String beanName = context.getReaderContext().generateBeanName(componentBuilder.getRawBeanDefinition());
componentBuilder.getRawBeanDefinition().setSource(context.extractSource(element));
componentBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
context.registerBeanComponent(new BeanComponentDefinition(componentBuilder.getBeanDefinition(), beanName));
return beanName;
}
}