/*
* Copyright 2013-2017 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.repository.support;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.convert.CassandraConverter;
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.query.CassandraEntityInformation;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
import org.springframework.util.Assert;
/**
* {@link CassandraEntityInformation} implementation using a {@link CassandraPersistentEntity} instance to lookup the
* necessary information.
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author Mark Paluch
*/
public class MappingCassandraEntityInformation<T, ID> extends AbstractEntityInformation<T, ID>
implements CassandraEntityInformation<T, ID> {
private final CassandraPersistentEntity<T> entityMetadata;
private final CassandraConverter converter;
private final boolean isPrimaryKeyEntity;
/**
* Create a new {@link MappingCassandraEntityInformation} for the given {@link CassandraPersistentEntity}.
*
* @param entity must not be {@literal null}.
*/
public MappingCassandraEntityInformation(CassandraPersistentEntity<T> entity, CassandraConverter converter) {
super(entity.getType());
this.entityMetadata = entity;
this.converter = converter;
this.isPrimaryKeyEntity = hasNonIdProperties(entity);
}
/* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public Optional<ID> getId(T entity) {
Assert.notNull(entity, "Entity must not be null");
Optional<CassandraPersistentProperty> idProperty = entityMetadata.getIdProperty();
// FIXME: Cast
return idProperty.map(p -> entityMetadata.getIdentifierAccessor(entity).getIdentifier())
.orElseGet(() -> Optional.ofNullable(converter.getId(entity, entityMetadata))).map(o -> (ID) o);
}
/* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#getIdType()
*/
@SuppressWarnings("unchecked")
@Override
public Class<ID> getIdType() {
return entityMetadata.getIdProperty().map(p -> (Class<ID>) p.getType()).orElse((Class<ID>) MapId.class);
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.repository.query.CassandraEntityMetadata#getTableName()
*/
@Override
public CqlIdentifier getTableName() {
return entityMetadata.getTableName();
}
@Override
public boolean isPrimaryKeyEntity() {
return isPrimaryKeyEntity;
}
private static boolean hasNonIdProperties(CassandraPersistentEntity<?> entity) {
final AtomicReference<Boolean> hasPrimaryKeyOnlyProperties = new AtomicReference<Boolean>(true);
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty property) {
if (property.isCompositePrimaryKey() || property.isPrimaryKeyColumn() || property.isIdProperty()) {
return;
}
hasPrimaryKeyOnlyProperties.set(false);
}
});
return hasPrimaryKeyOnlyProperties.get();
}
}