Package org.hivedb.hibernate

Source Code of org.hivedb.hibernate.ConfigurationReader

package org.hivedb.hibernate;

import org.hivedb.Hive;
import org.hivedb.HiveLockableException;
import org.hivedb.HiveRuntimeException;
import org.hivedb.annotations.*;
import org.hivedb.configuration.*;
import org.hivedb.management.HiveConfigurationSchemaInstaller;
import org.hivedb.meta.PartitionDimension;
import org.hivedb.meta.SecondaryIndex;
import org.hivedb.meta.persistence.CachingDataSourceProvider;
import org.hivedb.util.Lists;
import org.hivedb.util.PrimitiveUtils;
import org.hivedb.util.classgen.ReflectionTools;
import org.hivedb.util.database.JdbcTypeMapper;
import org.hivedb.util.functional.Atom;
import org.hivedb.util.functional.Filter;
import org.hivedb.util.functional.Predicate;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Method;
import java.util.*;

public class ConfigurationReader {
  private Map<String, EntityConfig> hiveConfigs = new HashMap<String, EntityConfig>();
  private PartitionDimension dimension = null;

  public ConfigurationReader(PartitionDimension partitionDimension) {
    dimension = partitionDimension;
  }

  public ConfigurationReader(Class<?>... classes) {
    for (Class<?> clazz : classes)
      if (isHiveEntity(clazz))
        configure(clazz);
  }

  public ConfigurationReader(Collection<Class<?>> classes) {
    for (Class<?> clazz : classes)
      if (isHiveEntity(clazz))
        configure(clazz);
  }

  private boolean isHiveEntity(Class<?> clazz) {
    return clazz.isAnnotationPresent(Resource.class);
  }

  public EntityConfig configure(Class<?> clazz) {
    EntityConfig config = readConfiguration(clazz);
    if (dimension == null)
      dimension = extractPartitionDimension(clazz);
    else if (!dimension.getName().equals(config.getPartitionDimensionName()))
      throw new UnsupportedOperationException(
        String.format("You are trying to configure on object from partition dimension %s into a Hive configured to use partition dimension %s. This is not supported. Use a separate configuration for each dimension.", config.getPartitionDimensionName(), dimension.getName()));

    hiveConfigs.put(clazz.getName(), config);
    return config;
  }

  @SuppressWarnings("unchecked")
  public static PartitionDimension extractPartitionDimension(Class clazz) {
    Method partitionIndexMethod = AnnotationHelper.getFirstMethodWithAnnotation(clazz, PartitionIndex.class);
    return new PartitionDimension(getPartitionDimensionName(clazz), JdbcTypeMapper.primitiveTypeToJdbcType(partitionIndexMethod.getReturnType()));
  }

  public static EntityConfig readConfiguration(Class<?> clazz) {
    PartitionDimension dimension = extractPartitionDimension(clazz);

    Method versionMethod = AnnotationHelper.getFirstMethodWithAnnotation(clazz, EntityVersion.class);
    Method resourceIdMethod = AnnotationHelper.getFirstMethodWithAnnotation(clazz, EntityId.class);
    Method partitionIndexMethod = AnnotationHelper.getFirstMethodWithAnnotation(clazz, PartitionIndex.class);

    String primaryIndexPropertyName = getIndexNameForMethod(partitionIndexMethod);
    String idPropertyName = getIndexNameForMethod(resourceIdMethod);
    String versionPropertyName = versionMethod == null ? null : getIndexNameForMethod(versionMethod);

    List<EntityIndexConfig> indexes = createIndexMethods(clazz, resourceIdMethod);

    EntityConfig config = new EntityConfigImpl(
      clazz,
      dimension.getName(),
      getResourceName(clazz),
      primaryIndexPropertyName,
      idPropertyName,
      versionPropertyName,
      indexes,
      partitionIndexMethod.getName().equals(resourceIdMethod.getName())
    );
    return config;
  }

  private static List<EntityIndexConfig> createIndexMethods(Class<?> clazz, Method resourceIdMethod) {
    Collection<Method> indexMethods = getIndexMethods(clazz, resourceIdMethod);
    List<EntityIndexConfig> indexes = Lists.newArrayList();

    for (Method indexMethod : indexMethods)
      if (isCollectionPropertyOfAComplexType(clazz, indexMethod))
        if (isIndexDelegate(indexMethod))
          indexes.add(new EntityIndexConfigProxy(clazz, getSecondaryIndexName(indexMethod), getIndexPropertyOfCollectionType(ReflectionTools.getCollectionItemType(clazz, ReflectionTools.getPropertyNameOfAccessor(indexMethod))), readConfiguration(getHiveForeignKeyIndexClass(indexMethod))));
        else
          indexes.add(new EntityIndexConfigImpl(clazz, getSecondaryIndexName(indexMethod), getIndexPropertyOfCollectionType(ReflectionTools.getCollectionItemType(clazz, ReflectionTools.getPropertyNameOfAccessor(indexMethod)))));
      else if (isIndexDelegate(indexMethod))
        indexes.add(new EntityIndexConfigProxy(clazz, getSecondaryIndexName(indexMethod), readConfiguration(getHiveForeignKeyIndexClass(indexMethod))));
      else
        indexes.add(new EntityIndexConfigImpl(clazz, getSecondaryIndexName(indexMethod)));
    return indexes;
  }

  @SuppressWarnings("unchecked")
  private static Collection<Method> getIndexMethods(Class<?> clazz, final Method resourceIdMethod) {
    return Filter.grep(new Predicate<Method>() {
      public boolean f(Method method) {
        return !method.equals(resourceIdMethod);
      }
    }, AnnotationHelper.getAllMethodsWithAnnotations(clazz, (Collection) Arrays.asList(Index.class, PartitionIndex.class)));
  }

  private static boolean isIndexDelegate(Method indexMethod) {
    return indexMethod.getAnnotation(IndexDelegate.class) != null;
  }

  private static Class<?> getHiveForeignKeyIndexClass(Method indexMethod) {
    try {
      return Class.forName(indexMethod.getAnnotation(IndexDelegate.class).value());
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Class not found " + indexMethod.getAnnotation(IndexDelegate.class).value());
    }
  }

  private static boolean isCollectionPropertyOfAComplexType(Class<?> clazz, Method indexMethod) {
    return ReflectionTools.isCollectionProperty(clazz, ReflectionTools.getPropertyNameOfAccessor(indexMethod)) &&
      !PrimitiveUtils.isPrimitiveClass(ReflectionTools.getCollectionItemType(clazz, ReflectionTools.getPropertyNameOfAccessor(indexMethod)));
  }

  @SuppressWarnings("unchecked")
  private static String getIndexPropertyOfCollectionType(Class collectionType) {
    try {
      return ReflectionTools.getPropertyNameOfAccessor(AnnotationHelper.getFirstMethodWithAnnotation(collectionType, Index.class));
    }
    catch (Exception e) {
      throw new RuntimeException(String.format("Unable to find an Index annotation for collection type %s", collectionType.getName()));
    }
  }

  public Collection<EntityConfig> getConfigurations() {
    return hiveConfigs.values();
  }

  public EntityConfig getEntityConfig(String className) {
    return hiveConfigs.get(className);
  }

  public EntityHiveConfig getHiveConfiguration() {
    EntityConfig prototype = Atom.getFirstOrThrow(hiveConfigs.values());
    return new PluralHiveConfig(hiveConfigs, prototype.getPartitionDimensionName(), prototype.getPrimaryKeyClass());
  }

  public void install(String uri) {
    new HiveConfigurationSchemaInstaller(uri).run();
    install(Hive.load(uri, CachingDataSourceProvider.getInstance()));
  }

  public void install(Hive hive) {
    Hive target = hive;
    if (hive.getPartitionDimension() == null) {
      target = Hive.create(hive.getUri(), dimension.getName(), dimension.getColumnType(), CachingDataSourceProvider.getInstance(), null);
    }

    for (EntityConfig config : hiveConfigs.values())
      installConfiguration(config, target);
  }

  public void installConfiguration(EntityConfig config, Hive hive) {
    try {
      // Duplicate installations are possible due to delegated indexes
      if (hive.doesResourceExist(config.getResourceName()))
        return;

      org.hivedb.meta.Resource resource =
        hive.addResource(createResource(config));

      for (EntityIndexConfig indexConfig : (Collection<EntityIndexConfig>) config.getEntityIndexConfigs())
        if (indexConfig.getIndexType().equals(IndexType.Delegates))
          installConfiguration(((EntityIndexConfigDelegator) indexConfig).getDelegateEntityConfig(), hive);
        else if (indexConfig.getIndexType().equals(IndexType.Hive)) {
          hive.addSecondaryIndex(resource, createSecondaryIndex(indexConfig));
        }

    } catch (HiveLockableException e) {
      throw new HiveRuntimeException(e.getMessage(), e);
    }
  }

  private SecondaryIndex createSecondaryIndex(EntityIndexConfig config) {
    return new SecondaryIndex(config.getIndexName(), JdbcTypeMapper.primitiveTypeToJdbcType(config.getIndexClass()));
  }

  private org.hivedb.meta.Resource createResource(EntityConfig config) {
    return new org.hivedb.meta.Resource(
      config.getResourceName(),
      JdbcTypeMapper.primitiveTypeToJdbcType(config.getIdClass()),
      config.isPartitioningResource());
  }

  public static String getResourceName(Class<?> clazz) {
    Resource resource = clazz.getAnnotation(Resource.class);
    if (resource != null)
      return resource.value();
    else
      return getResourceNameForClass(clazz);
  }

  private static String getPartitionDimensionName(Class<?> clazz) {
    String name = AnnotationHelper.getFirstInstanceOfAnnotation(clazz, PartitionIndex.class).value();
    Method m = AnnotationHelper.getFirstMethodWithAnnotation(clazz, PartitionIndex.class);
    return "".equals(name) ? getIndexNameForMethod(m) : name;
  }

  private static String getSecondaryIndexName(Method method) {
    Index annotation = method.getAnnotation(Index.class);
    if (annotation != null && !"".equals(annotation.name()))
      return annotation.name();
    else
      return getIndexNameForMethod(method);
  }

  public static String getIndexNameForMethod(Method method) {
    return BeanUtils.findPropertyForMethod(method).getDisplayName();
  }

  public static String getResourceNameForClass(Class<?> clazz) {
    return clazz.getName().replace('.', '_');
  }
}
TOP

Related Classes of org.hivedb.hibernate.ConfigurationReader

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.