/*
* Copyright 2002-2006 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.orm.jpa.config;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.core.Conventions;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter;
import org.springframework.util.StringUtils;
/**
* @author Costin Leau
* @since 2.0
*/
public class JpaNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("entityManagerFactory", new ConfigBeanDefinitionParser());
}
private class ConfigBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private static final String VENDOR = "vendor";
private static final String VENDOR_PROVIDED = "provided";
private static final String VENDOR_CUSTOM = "custom";
private static final String ID_ATTRIBUTE = "id";
private static final String LOAD_TIME_WEAVER = "load-time-weaver";
protected Class getBeanClass(Element element) {
return LocalEntityManagerFactoryBean.class;
}
protected void doParse(Element element, BeanDefinitionBuilder builder) {
configureAttributes(element, builder);
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = node.getLocalName();
if (VENDOR.equals(localName)) {
parseVendor((Element) node, builder);
}
}
}
}
private void configureAttributes(Element element, BeanDefinitionBuilder builder) {
NamedNodeMap attributes = element.getAttributes();
for (int x = 0; x < attributes.getLength(); x++) {
Attr attribute = (Attr) attributes.item(x);
String name = attribute.getLocalName();
if (ID_ATTRIBUTE.equals(name)) {
continue;
}
if (LOAD_TIME_WEAVER.equals(name)) {
builder.getBeanDefinition().setBeanClass(LocalContainerEntityManagerFactoryBean.class);
}
builder.addPropertyValue(extractPropertyName(name), attribute.getValue());
}
}
private String extractPropertyName(String attributeName) {
return Conventions.attributeNameToPropertyName(attributeName);
}
private void parseVendor(Element element, BeanDefinitionBuilder builder) {
BeanDefinitionBuilder vendorBuilder = BeanDefinitionBuilder.rootBeanDefinition(JpaVendorAdapter.class);
configureAttributes(element, vendorBuilder);
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = node.getLocalName();
if (VENDOR_PROVIDED.equals(localName)) {
String name = ((Element) node).getAttribute("name");
if (StringUtils.hasText(name)) {
if ("toplink".equals(name))
vendorBuilder.getBeanDefinition().setBeanClass(TopLinkJpaVendorAdapter.class);
else if ("hibernate".equals(name))
vendorBuilder.getBeanDefinition().setBeanClass(HibernateJpaVendorAdapter.class);
}
}
else if (VENDOR_CUSTOM.equals(localName)) {
String clazz = ((Element) node).getAttribute("class");
if (StringUtils.hasText(clazz))
vendorBuilder.getBeanDefinition().setBeanClassName(clazz);
}
}
}
builder.addPropertyValue("jpaVendorAdapter", vendorBuilder.getBeanDefinition());
}
}
}