org.springframework.data.cassandra.config.CassandraMappingContextParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-data-cassandra Show documentation
Show all versions of spring-data-cassandra Show documentation
Cassandra support for Spring Data
/*
* Copyright 2013-2023 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
*
* https://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.data.cassandra.config;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.EntityMapping;
import org.springframework.data.cassandra.core.mapping.Mapping;
import org.springframework.data.cassandra.core.mapping.PropertyMapping;
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Spring Data Cassandra XML namespace parser for the {@code cassandra:mapping} element.
*
* @author Matthew T. Adams
* @author Mark Paluch
*/
class CassandraMappingContextParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class getBeanClass(Element element) {
return CassandraMappingContext.class;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return (StringUtils.hasText(id) ? id : DefaultBeanNames.CONTEXT);
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
parseMapping(element, builder, parserContext.getReaderContext().getBeanClassLoader());
builder.getRawBeanDefinition().setSource(element);
}
private void parseMapping(Element element, BeanDefinitionBuilder builder, ClassLoader classLoader) {
String packages = element.getAttribute("entity-base-packages");
if (StringUtils.hasText(packages)) {
try {
CassandraEntityClassScanner scanner = new CassandraEntityClassScanner();
scanner.setBeanClassLoader(classLoader);
scanner.setEntityBasePackages(StringUtils.commaDelimitedListToSet(packages));
Set> entityClasses = scanner.scanForEntityClasses();
builder.addPropertyValue("initialEntitySet", entityClasses);
} catch (Exception x) {
throw new IllegalArgumentException(
String.format("encountered exception while scanning for entity classes in package(s) [%s]", packages), x);
}
}
Set mappings = new HashSet<>();
DomUtils.getChildElementsByTagName(element, "entity").forEach(entity -> {
EntityMapping entityMapping = parseEntity(entity);
mappings.add(entityMapping);
});
List userTypeResolvers = DomUtils.getChildElementsByTagName(element, "user-type-resolver");
String userTypeResolverRef = element.getAttribute("user-type-resolver-ref");
if (StringUtils.hasText(userTypeResolverRef)) {
Assert.isTrue(userTypeResolvers.isEmpty(), "Must not define user-type-resolver and user-type-resolver-ref");
builder.addPropertyReference("userTypeResolver", userTypeResolverRef);
}
if (!userTypeResolvers.isEmpty()) {
BeanDefinition userTypeResolver = parseUserTypeResolver(userTypeResolvers.get(0));
builder.addPropertyValue("userTypeResolver", userTypeResolver);
}
Mapping mapping = new Mapping();
mapping.setEntityMappings(mappings);
builder.addPropertyValue("mapping", mapping);
}
private EntityMapping parseEntity(Element entity) {
String className = entity.getAttribute("class");
Assert.state(StringUtils.hasText(className), "class attribute must not be empty");
Element table = DomUtils.getChildElementByTagName(entity, "table");
String tableName = "";
String forceQuote = "";
if (table != null) {
tableName = table.getAttribute("name");
tableName = (StringUtils.hasText(tableName) ? tableName : "");
forceQuote = String.valueOf(Boolean.parseBoolean(table.getAttribute("force-quote")));
}
Map propertyMappings = parsePropertyMappings(entity);
EntityMapping entityMapping = new EntityMapping(className, tableName, forceQuote);
entityMapping.setPropertyMappings(propertyMappings);
return entityMapping;
}
private BeanDefinition parseUserTypeResolver(Element entity) {
String sessionRef = entity.getAttribute("session-ref");
if (StringUtils.hasText(sessionRef)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SimpleUserTypeResolver.class);
builder.addConstructorArgReference(sessionRef);
return builder.getBeanDefinition();
}
String keyspaceName = entity.getAttribute("keyspace-name");
Assert.state(StringUtils.hasText(keyspaceName), "keyspace-name attribute must not be null or empty");
String clusterRef = entity.getAttribute("cluster-ref");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SimpleUserTypeResolver.class);
builder.addConstructorArgReference(StringUtils.hasText(clusterRef) ? clusterRef : DefaultCqlBeanNames.CLUSTER);
builder.addConstructorArgValue(keyspaceName);
return builder.getBeanDefinition();
}
private Map parsePropertyMappings(Element entity) {
Map propertyMappings = new HashMap<>();
for (Element property : DomUtils.getChildElementsByTagName(entity, "property")) {
String value = property.getAttribute("name");
Assert.state(StringUtils.hasText(value), "name attribute must not be empty");
PropertyMapping propertyMapping = new PropertyMapping(value);
value = property.getAttribute("column-name");
if (StringUtils.hasText(value)) {
propertyMapping.setColumnName(value);
}
value = property.getAttribute("force-quote");
if (StringUtils.hasText(value)) {
propertyMapping.setForceQuote(value);
}
propertyMappings.put(propertyMapping.getPropertyName(), propertyMapping);
}
return propertyMappings;
}
}