org.springframework.data.cassandra.convert.MappingCassandraConverter 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-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.data.cassandra.convert;
import java.io.Serializable;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.repository.MapId;
import org.springframework.data.cassandra.repository.MapIdentifiable;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.SpELContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.querybuilder.Delete.Where;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
import static org.springframework.data.cassandra.repository.support.BasicMapId.id;
/**
* {@link CassandraConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link Row}.
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author Oliver Gierke
*/
public class MappingCassandraConverter extends AbstractCassandraConverter implements CassandraConverter,
ApplicationContextAware, BeanClassLoaderAware {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final CassandraMappingContext mappingContext;
protected ApplicationContext applicationContext;
protected SpELContext spELContext;
protected ClassLoader beanClassLoader;
/**
* Creates a new {@link MappingCassandraConverter} with a {@link BasicCassandraMappingContext}.
*/
public MappingCassandraConverter() {
this(new BasicCassandraMappingContext());
}
/**
* Creates a new {@link MappingCassandraConverter} with the given {@link CassandraMappingContext}.
*
* @param mappingContext must not be {@literal null}.
*/
public MappingCassandraConverter(CassandraMappingContext mappingContext) {
super(new DefaultConversionService());
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
}
@SuppressWarnings("unchecked")
public R readRow(Class clazz, Row row) {
Class beanClassLoaderClass = transformClassToBeanClassLoaderClass(clazz);
TypeInformation type = ClassTypeInformation.from(beanClassLoaderClass);
TypeInformation typeToUse = type;
Class rawType = typeToUse.getType();
if (Row.class.isAssignableFrom(rawType)) {
return (R) row;
}
CassandraPersistentEntity persistentEntity = (CassandraPersistentEntity) mappingContext
.getPersistentEntity(typeToUse);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
return readEntityFromRow(persistentEntity, row);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
this.spELContext = new SpELContext(this.spELContext, applicationContext);
}
protected S readEntityFromRow(final CassandraPersistentEntity entity, final Row row) {
DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
BasicCassandraRowValueProvider rowValueProvider = new BasicCassandraRowValueProvider(row, evaluator);
CassandraPersistentEntityParameterValueProvider parameterProvider = new CassandraPersistentEntityParameterValueProvider(
entity, rowValueProvider, null);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, parameterProvider);
BeanWrapper wrapper = BeanWrapper.create(instance, conversionService);
readPropertiesFromRow(entity, rowValueProvider, wrapper);
return wrapper.getBean();
}
protected void readPropertiesFromRow(final CassandraPersistentEntity entity,
final BasicCassandraRowValueProvider row, final BeanWrapper wrapper) {
entity.doWithProperties(new PropertyHandler() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
MappingCassandraConverter.this.readPropertyFromRow(entity, prop, row, wrapper);
}
});
}
protected void readPropertyFromRow(final CassandraPersistentEntity entity, final CassandraPersistentProperty prop,
final BasicCassandraRowValueProvider row, final BeanWrapper wrapper) {
if (entity.isConstructorArgument(prop)) { // skip 'cause prop was set in ctor
return;
}
if (prop.isCompositePrimaryKey()) {
// get the key
CassandraPersistentProperty keyProperty = entity.getIdProperty();
Object key = wrapper.getProperty(keyProperty);
if (key == null) {
key = instantiatePrimaryKey(keyProperty.getCompositePrimaryKeyEntity(), keyProperty, row);
}
// wrap the key
BeanWrapper