DATACASS-91 - improved XML parsing & Java config

This commit is contained in:
Matthew Adams
2014-02-11 11:05:38 -06:00
parent 0f121597f2
commit 24be302c03
10 changed files with 60 additions and 223 deletions

View File

@@ -22,7 +22,7 @@ import static org.springframework.cassandra.config.xml.ParsingUtils.addRequiredP
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.util.StringUtils;
@@ -37,7 +37,7 @@ import org.w3c.dom.NamedNodeMap;
* @author David Webb
* @author Matthew T. Adams
*/
public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
public class CassandraSessionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.cassandra.config.xml;
import static org.springframework.cassandra.config.xml.ParsingUtils.*;
import static org.springframework.cassandra.config.xml.ParsingUtils.addOptionalPropertyReference;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.config.CassandraTemplateFactoryBean;
import org.springframework.util.StringUtils;
@@ -32,7 +32,7 @@ import org.w3c.dom.Element;
* @author David Webb
* @author Matthew T. Adams
*/
public class CassandraTemplateParser extends AbstractSimpleBeanDefinitionParser {
public class CassandraTemplateParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {

View File

@@ -1,6 +1,7 @@
package org.springframework.data.cassandra.config;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -22,6 +23,23 @@ import org.springframework.util.StringUtils;
*/
public class CassandraEntityClassScanner {
public static Set<Class<?>> scan(String... entityBasePackages) throws ClassNotFoundException {
return new CassandraEntityClassScanner(entityBasePackages).scanForEntityClasses();
}
public static Set<Class<?>> scan(Class<?>... entityBasePackageClasses) throws ClassNotFoundException {
return new CassandraEntityClassScanner(entityBasePackageClasses).scanForEntityClasses();
}
public static Set<Class<?>> scan(Collection<String> entityBasePackages) throws ClassNotFoundException {
return new CassandraEntityClassScanner(entityBasePackages).scanForEntityClasses();
}
public static Set<Class<?>> scan(Collection<String> entityBasePackages, Collection<Class<?>> entityBasePackageClasses)
throws ClassNotFoundException {
return new CassandraEntityClassScanner(entityBasePackages, entityBasePackageClasses).scanForEntityClasses();
}
protected Set<String> entityBasePackages = new HashSet<String>();
protected Set<Class<?>> entityBasePackageClasses = new HashSet<Class<?>>();
protected ClassLoader beanClassLoader;
@@ -29,6 +47,14 @@ public class CassandraEntityClassScanner {
public CassandraEntityClassScanner() {
}
public CassandraEntityClassScanner(Class<?>... entityBasePackageClasses) {
this(null, Arrays.asList(entityBasePackageClasses));
}
public CassandraEntityClassScanner(String... entityBasePackages) {
this(Arrays.asList(entityBasePackages));
}
public CassandraEntityClassScanner(Collection<String> entityBasePackages) {
this(entityBasePackages, null);
}

View File

@@ -1,73 +0,0 @@
package org.springframework.data.cassandra.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.util.Assert;
public class CassandraMappingContextFactoryBean implements FactoryBean<CassandraMappingContext>, InitializingBean {
protected Set<String> entityBasePackages = new HashSet<String>();
protected Mapping mapping;
protected ClassLoader beanClassLoader;
@Override
public void afterPropertiesSet() throws Exception {
mapping = mapping == null ? new Mapping() : mapping;
}
@Override
public CassandraMappingContext getObject() throws Exception {
DefaultCassandraMappingContext mappingContext = new DefaultCassandraMappingContext();
mappingContext.setInitialEntitySet(new CassandraEntityClassScanner(entityBasePackages).scanForEntityClasses());
mappingContext.setMapping(mapping);
mappingContext.setBeanClassLoader(beanClassLoader);
mappingContext.initialize(); // this is necessary here
return mappingContext;
}
@Override
public Class<?> getObjectType() {
return CassandraMappingContext.class;
}
@Override
public boolean isSingleton() {
return true;
}
public Set<String> getEntityBasePackages() {
return entityBasePackages;
}
public void setEntityBasePackages(Set<String> basePackages) {
this.entityBasePackages = basePackages == null ? new HashSet<String>() : new HashSet<String>(basePackages);
}
public Mapping getMapping() {
return mapping;
}
public void setMapping(Mapping mapping) {
Assert.notNull(mapping);
this.mapping = mapping;
}
public ClassLoader getBeanClassLoader() {
return beanClassLoader;
}
public void setBeanClassLoader(ClassLoader entityClassLoader) {
this.beanClassLoader = entityClassLoader;
}
}

View File

@@ -1,49 +0,0 @@
package org.springframework.data.cassandra.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.util.Assert;
public class CassandraMappingConverterFactoryBean implements FactoryBean<CassandraConverter>, InitializingBean {
protected CassandraMappingContext mappingContext;
protected Set<String> basePackages = new HashSet<String>();
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(mappingContext);
Assert.notNull(basePackages);
}
@Override
public CassandraConverter getObject() throws Exception {
return new MappingCassandraConverter(mappingContext);
}
@Override
public Class<?> getObjectType() {
return CassandraConverter.class;
}
@Override
public boolean isSingleton() {
return true;
}
public CassandraMappingContext getMappingContext() {
return mappingContext;
}
public void setMappingContext(CassandraMappingContext mappingContext) {
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
}
}

View File

@@ -15,22 +15,19 @@
*/
package org.springframework.data.cassandra.config.java;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.cassandra.config.java.AbstractClusterConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.CassandraDataSessionFactoryBean;
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
import org.springframework.data.cassandra.config.CassandraMappingContextFactoryBean;
import org.springframework.data.cassandra.config.CassandraMappingConverterFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.mapping.context.MappingContext;
@@ -69,7 +66,7 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
CassandraDataSessionFactoryBean bean = new CassandraDataSessionFactoryBean();
bean.setCluster(cluster().getObject());
bean.setConverter(cassandraConverter().getObject());
bean.setConverter(cassandraConverter());
bean.setSchemaAction(getSchemaAction());
bean.setKeyspaceName(getKeyspaceName());
bean.setStartupScripts(getStartupScripts());
@@ -85,7 +82,7 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
*/
@Bean
public CassandraAdminOperations cassandraTemplate() throws Exception {
return new CassandraAdminTemplate(session().getObject(), cassandraConverter().getObject());
return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
}
/**
@@ -94,10 +91,10 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
* @throws ClassNotFoundException
*/
@Bean
public CassandraMappingContextFactoryBean cassandraMapping() throws ClassNotFoundException {
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
CassandraMappingContextFactoryBean bean = new CassandraMappingContextFactoryBean();
bean.setEntityBasePackages(new HashSet<String>(Arrays.asList(getEntityBasePackages())));
DefaultCassandraMappingContext bean = new DefaultCassandraMappingContext();
bean.setInitialEntitySet(CassandraEntityClassScanner.scan(getEntityBasePackages()));
bean.setBeanClassLoader(beanClassLoader);
return bean;
@@ -107,32 +104,8 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
* Return the {@link CassandraConverter} instance to convert Rows to Objects, Objects to BuiltStatements
*/
@Bean
public CassandraMappingConverterFactoryBean cassandraConverter() throws Exception {
CassandraMappingConverterFactoryBean bean = new CassandraMappingConverterFactoryBean();
bean.setMappingContext(cassandraMapping().getObject());
return bean;
}
/**
* Scans the mapping base package for entity classes.
*
* @see #getEntityBasePackages()
* @see #getEntityScanner()
* @return <code>Set&lt;Class&lt;?&gt;&gt;</code> representing the annotated entity classes found.
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
CassandraEntityClassScanner entityScanner = getEntityScanner();
entityScanner.setEntityBasePackages(Arrays.asList(getEntityBasePackages()));
return entityScanner.scanForEntityClasses();
}
public CassandraEntityClassScanner getEntityScanner() {
return new CassandraEntityClassScanner();
public CassandraConverter cassandraConverter() throws Exception {
return new MappingCassandraConverter(cassandraMapping());
}
@Override

View File

@@ -6,10 +6,10 @@ import java.util.Set;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.config.CassandraMappingContextFactoryBean;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.EntityMapping;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.util.StringUtils;
@@ -21,11 +21,11 @@ import org.w3c.dom.Element;
*
* @author Matthew T. Adams
*/
public class CassandraMappingContextParser extends AbstractSimpleBeanDefinitionParser {
public class CassandraMappingContextParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraMappingContextFactoryBean.class;
return DefaultCassandraMappingContext.class;
}
@Override
@@ -37,33 +37,17 @@ public class CassandraMappingContextParser extends AbstractSimpleBeanDefinitionP
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
parseBasePackagesAttribute(element, parserContext, builder);
parseMapping(element, parserContext, builder);
protected void doParse(Element element, BeanDefinitionBuilder builder) {
parseMapping(element, builder);
}
protected void parseBasePackagesAttribute(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String basePackages = element.getAttribute("entity-base-packages");
if (!StringUtils.hasText(basePackages)) {
return;
}
Set<String> basePackageSet = StringUtils.commaDelimitedListToSet(basePackages);
builder.addPropertyValue("entityBasePackages", basePackageSet);
}
protected void parseMapping(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
// TODO: parse <mapping> **attributes** here, if there ever are any
protected void parseMapping(Element element, BeanDefinitionBuilder builder) {
Set<EntityMapping> mappings = new HashSet<EntityMapping>();
for (Element child : DomUtils.getChildElementsByTagName(element, "entity")) {
for (Element entity : DomUtils.getChildElementsByTagName(element, "entity")) {
EntityMapping entityMapping = parseEntity(child);
EntityMapping entityMapping = parseEntity(entity);
if (entityMapping != null) {
mappings.add(entityMapping);

View File

@@ -3,10 +3,10 @@ package org.springframework.data.cassandra.config.xml;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.config.CassandraMappingConverterFactoryBean;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -15,11 +15,11 @@ import org.w3c.dom.Element;
*
* @author Matthew T. Adams
*/
public class CassandraMappingConverterParser extends AbstractSimpleBeanDefinitionParser {
public class CassandraMappingConverterParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraMappingConverterFactoryBean.class;
return MappingCassandraConverter.class;
}
@Override
@@ -31,21 +31,13 @@ public class CassandraMappingConverterParser extends AbstractSimpleBeanDefinitio
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected void doParse(Element element, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
parseMappingContextAttribute(element, parserContext, builder);
}
protected void parseMappingContextAttribute(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
String mappingContextRef = element.getAttribute("mapping-ref");
if (!StringUtils.hasText(mappingContextRef)) {
mappingContextRef = DefaultDataBeanNames.MAPPING_CONTEXT;
String mappingRef = element.getAttribute("mapping-ref");
if (!StringUtils.hasText(mappingRef)) {
mappingRef = DefaultDataBeanNames.MAPPING_CONTEXT;
}
builder.addPropertyReference("mappingContext", mappingContextRef);
builder.addConstructorArgReference(mappingRef);
}
}

View File

@@ -56,7 +56,6 @@ public class DefaultCassandraMappingContext extends
protected ApplicationContext context;
protected Mapping mapping = new Mapping();
protected ClassLoader beanClassLoader;
protected boolean initialized;
// useful caches
protected Map<String, Set<CassandraPersistentEntity<?>>> entitySetsByTableName = new HashMap<String, Set<CassandraPersistentEntity<?>>>();
@@ -70,27 +69,12 @@ public class DefaultCassandraMappingContext extends
setSimpleTypeHolder(new CassandraSimpleTypeHolder());
}
@Override
public void afterPropertiesSet() {
if (initialized) {
return;
}
super.afterPropertiesSet();
}
@Override
public void initialize() {
if (initialized) {
return;
}
super.initialize();
processMappingOverrides();
initialized = true;
}
@Override

View File

@@ -10,7 +10,7 @@
<context:property-placeholder
location="classpath:/spring-data-cassandra-build.properties" />
<cass:converter />
<cass:converter mapping-ref="cassandraMapping"/>
<cass:template />