Package org.springframework.data.cassandra.mapping

Source Code of org.springframework.data.cassandra.mapping.BasicCassandraMappingContext

/*
* 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.mapping;

import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId;
import static org.springframework.cassandra.core.keyspace.CreateTableSpecification.createTable;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.AbstractMappingContext;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import com.datastax.driver.core.TableMetadata;

/**
* Default implementation of a {@link MappingContext} for Cassandra using {@link CassandraPersistentEntity} and
* {@link CassandraPersistentProperty} as primary abstractions.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class BasicCassandraMappingContext extends
    AbstractMappingContext<CassandraPersistentEntity<?>, CassandraPersistentProperty> implements
    CassandraMappingContext, ApplicationContextAware {

  protected ApplicationContext context;
  protected Mapping mapping = new Mapping();
  protected ClassLoader beanClassLoader;
  protected CassandraPersistentEntityMetadataVerifier verifier = new BasicCassandraPersistentEntityMetadataVerifier();

  // useful caches
  protected Map<CqlIdentifier, Set<CassandraPersistentEntity<?>>> entitySetsByTableName = new HashMap<CqlIdentifier, Set<CassandraPersistentEntity<?>>>();
  protected Set<CassandraPersistentEntity<?>> nonPrimaryKeyEntities = new HashSet<CassandraPersistentEntity<?>>();
  protected Set<CassandraPersistentEntity<?>> primaryKeyEntities = new HashSet<CassandraPersistentEntity<?>>();
  protected Map<Class<?>, CassandraPersistentEntity<?>> entitiesByType = new HashMap<Class<?>, CassandraPersistentEntity<?>>();

  /**
   * Creates a new {@link BasicCassandraMappingContext}.
   */
  public BasicCassandraMappingContext() {
    setSimpleTypeHolder(new CassandraSimpleTypeHolder());
  }

  @Override
  public void initialize() {

    super.initialize();

    processMappingOverrides();
  }

  @Override
  public Collection<CassandraPersistentEntity<?>> getPersistentEntities() {
    return getPersistentEntities(false);
  }

  @Override
  public Collection<CassandraPersistentEntity<?>> getPrimaryKeyEntities() {
    return Collections.unmodifiableSet(primaryKeyEntities);
  }

  @Override
  public Collection<CassandraPersistentEntity<?>> getNonPrimaryKeyEntities() {
    return Collections.unmodifiableSet(nonPrimaryKeyEntities);
  }

  @Override
  public Collection<CassandraPersistentEntity<?>> getPersistentEntities(boolean includePrimaryKeyTypes) {
    if (includePrimaryKeyTypes) {
      return super.getPersistentEntities();
    }
    return Collections.unmodifiableSet(nonPrimaryKeyEntities);
  }

  @Override
  public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
      CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {

    return createPersistentProperty(field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder);
  }

  public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
      CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {

    return new BasicCassandraPersistentProperty(field, descriptor, owner, simpleTypeHolder);
  }

  @Override
  protected <T> CassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {

    CassandraPersistentEntity<T> entity = new BasicCassandraPersistentEntity<T>(typeInformation, this, verifier);

    if (context != null) {
      entity.setApplicationContext(context);
    }

    // now do some caching of the entity

    Set<CassandraPersistentEntity<?>> entities = entitySetsByTableName.get(entity.getTableName());
    if (entities == null) {
      entities = new HashSet<CassandraPersistentEntity<?>>();
    }
    entities.add(entity);
    entitySetsByTableName.put(entity.getTableName(), entities);

    if (entity.isCompositePrimaryKey()) {
      primaryKeyEntities.add(entity);
    } else {
      nonPrimaryKeyEntities.add(entity);
    }

    entitiesByType.put(entity.getType(), entity);

    return entity;
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.context = applicationContext;
  }

  @Override
  public boolean usesTable(TableMetadata table) {
    return entitySetsByTableName.containsKey(table.getName());
  }

  @Override
  public CreateTableSpecification getCreateTableSpecificationFor(CassandraPersistentEntity<?> entity) {

    Assert.notNull(entity);

    final CreateTableSpecification spec = createTable().name(entity.getTableName());

    entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {

      @Override
      public void doWithPersistentProperty(CassandraPersistentProperty prop) {

        if (prop.isCompositePrimaryKey()) {

          CassandraPersistentEntity<?> pkEntity = getPersistentEntity(prop.getRawType());

          pkEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {

            @Override
            public void doWithPersistentProperty(CassandraPersistentProperty pkProp) {

              if (pkProp.isPartitionKeyColumn()) {
                spec.partitionKeyColumn(pkProp.getColumnName(), pkProp.getDataType());
              } else { // it's a cluster column
                spec.clusteredKeyColumn(pkProp.getColumnName(), pkProp.getDataType(), pkProp.getPrimaryKeyOrdering());
              }
            }
          });

        } else {

          if (prop.isIdProperty() || prop.isPartitionKeyColumn()) {
            spec.partitionKeyColumn(prop.getColumnName(), prop.getDataType());
          } else if (prop.isClusterKeyColumn()) {
            spec.clusteredKeyColumn(prop.getColumnName(), prop.getDataType());
          } else {
            spec.column(prop.getColumnName(), prop.getDataType());
          }
        }
      }

    });

    if (spec.getPartitionKeyColumns().isEmpty()) {
      throw new MappingException("no partition key columns found in the entity " + entity.getType());
    }

    return spec;
  }

  public void setMapping(Mapping mapping) {

    Assert.notNull(mapping);

    this.mapping = mapping;
  }

  protected void processMappingOverrides() {

    if (mapping == null) {
      return;
    }

    for (EntityMapping entityMapping : mapping.getEntityMappings()) {

      if (entityMapping == null) {
        continue;
      }

      String entityClassName = entityMapping.getEntityClassName();
      Class<?> entityClass;
      try {
        entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
      } catch (ClassNotFoundException e) {
        throw new IllegalStateException(String.format("unknown persistent entity name [%s]", entityClassName), e);
      }

      CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);

      if (entity == null) {
        throw new IllegalStateException(String.format("unknown persistent entity class name [%s]", entityClassName));
      }

      String tableName = entityMapping.getTableName();
      if (StringUtils.hasText(tableName)) {
        entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote())));
      }

      processMappingOverrides(entity, entityMapping);
    }
  }

  protected void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {

    for (PropertyMapping mapping : entityMapping.getPropertyMappings().values()) {
      processMappingOverride(entity, mapping);
    }
  }

  protected void processMappingOverride(CassandraPersistentEntity<?> entity, PropertyMapping mapping) {

    CassandraPersistentProperty property = entity.getPersistentProperty(mapping.getPropertyName());
    if (property == null) {
      throw new IllegalArgumentException(String.format("entity class [%s] has no persistent property named [%s]",
          entity.getType().getName(), mapping.getPropertyName()));
    }

    boolean forceQuote = false;
    String value = mapping.getForceQuote();
    if (StringUtils.hasText(value)) {
      property.setForceQuote(forceQuote = Boolean.valueOf(value));
    }

    value = mapping.getColumnName();

    if (StringUtils.hasText(value)) {
      property.setColumnName(cqlId(value, forceQuote));
    }

  }

  public void setBeanClassLoader(ClassLoader beanClassLoader) {
    this.beanClassLoader = beanClassLoader;
  }

  @Override
  public CassandraPersistentEntity<?> getExistingPersistentEntity(Class<?> type) {

    CassandraPersistentEntity<?> entity = entitiesByType.get(type);
    if (entity != null) {
      return entity;
    }

    throw new IllegalArgumentException(String.format("unknown persistent type [%s]", type.getName()));
  }

  @Override
  public boolean contains(Class<?> type) {
    return entitiesByType.containsKey(type);
  }

  /**
   * @return Returns the verifier.
   */
  public CassandraPersistentEntityMetadataVerifier getVerifier() {
    return verifier;
  }

  /**
   * @param verifier The verifier to set.
   */
  @Override
  public void setVerifier(CassandraPersistentEntityMetadataVerifier verifier) {
    this.verifier = verifier;
  }
}
TOP

Related Classes of org.springframework.data.cassandra.mapping.BasicCassandraMappingContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.