Package org.hivedb.util.classgen

Source Code of org.hivedb.util.classgen.GeneratedServiceInterceptor

package org.hivedb.util.classgen;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.hibernate.shards.strategy.access.ShardAccessStrategy;
import org.hibernate.shards.util.Lists;
import org.hivedb.Hive;
import org.hivedb.HiveRuntimeException;
import org.hivedb.annotations.AnnotationHelper;
import org.hivedb.annotations.IndexParam;
import org.hivedb.annotations.IndexParamPagingPair;
import org.hivedb.annotations.IndexParamPairs;
import org.hivedb.configuration.EntityConfig;
import org.hivedb.configuration.EntityHiveConfig;
import org.hivedb.hibernate.*;
import org.hivedb.services.Service;
import org.hivedb.services.ServiceContainer;
import org.hivedb.services.ServiceResponse;
import org.hivedb.util.PrimitiveUtils;
import org.hivedb.util.functional.*;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.Map.Entry;

public class GeneratedServiceInterceptor implements MethodInterceptor, Service {

  public static Service load(String className, String serviceClassName, String serviceResponseClassName, String serviceContainerClassName, Hive hive, EntityHiveConfig entityHiveConfig, ShardAccessStrategy strategy) {
    try {
      return load(Class.forName(className), Class.forName(serviceClassName), Class.forName(serviceResponseClassName), Class.forName(serviceContainerClassName), hive, entityHiveConfig, strategy);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }

  public static Service load(Class clazz, Class serviceClass, Class serviceResponseClass, Class serviceContainerClass, Hive hive, EntityHiveConfig entityHiveConfig, ShardAccessStrategy strategy) {
    EntityConfig config = entityHiveConfig.getEntityConfig(clazz.getCanonicalName());
    List<Class<?>> classes = Lists.newArrayList();
    classes.addAll(new EntityResolver(entityHiveConfig).getEntityClasses());
    HiveSessionFactory factory = new HiveSessionFactoryBuilderImpl(entityHiveConfig, hive, strategy);
    DataAccessObject dao = new BaseDataAccessObject(config, hive, factory);
    return (Service) GeneratedClassFactory.newInstance(serviceClass, new GeneratedServiceInterceptor(clazz, serviceClass, serviceResponseClass, serviceContainerClass, dao, config));
  }

  public static Service load(Class clazz, Class serviceClass, Class serviceResponseClass, Class serviceContainerClass, Hive hive, ConfigurationReader reader, ShardAccessStrategy strategy) {
    return load(clazz, serviceClass, serviceResponseClass, serviceContainerClass, hive, reader.getHiveConfiguration(), strategy);
  }

  Class clazz;
  Class serviceClass;
  Class serviceResponseClass;
  Class serviceContainerClass;
  DataAccessObject dao;
  EntityConfig config;

  public GeneratedServiceInterceptor(Class clazz, Class serviceClass, Class serviceResponseClass, Class serviceContainerClass, DataAccessObject dao, EntityConfig config) {
    this.clazz = clazz;
    this.serviceClass = serviceClass;
    this.serviceResponseClass = serviceResponseClass;
    this.serviceContainerClass = serviceContainerClass;
    this.dao = dao;
    this.config = config;
  }

  public Collection<Object> unProxy(Collection<Object> classInstances) {
    return Transform.map(new Unary<Object, Object>() {
      public Object f(Object item) {
        return unProxy(item);
      }
    }, classInstances);
  }

  public Object unProxy(Object instance) {
    return new GenerateInstance(clazz).generateAndCopyProperties(instance);
  }

  public boolean exists(Object id) {
    return dao.exists(id);
  }

  public String getPersistedClass() {
    return clazz.getName();
  }

  public Object delete(Object id) {
    dao.delete(id);
    return id;
  }

  public ServiceResponse get(Object id) {
    final Object instance = dao.get(id);
    return formulateResponse((Collection<Object>) (instance != null ? Arrays.asList(instance) : Collections.emptyList()));
  }


  public ServiceResponse save(Object instance) {
    return formulateResponse(dao.save(unProxy(instance)));
  }

  public ServiceResponse saveAll(Iterable instances) {
    return formulateResponse(dao.saveAll((Collection) unProxy((Collection) instances)));
  }


  @SuppressWarnings("unchecked")
  private ServiceResponse formulateResponse(Object... instances) {
    return formulateResponse(Arrays.asList(instances));
  }

  @SuppressWarnings("unchecked")
  private ServiceResponse formulateResponse(Collection instances) {
    validateNonNull(instances);
    ServiceResponse serviceResponse = createServiceResponse(instances);
    return serviceResponse;
  }

  public ServiceResponse createServiceResponse(Collection instances) {
    ServiceResponse serviceResponse = (ServiceResponse) GeneratedClassFactory.newInstance(serviceResponseClass);
    GeneratedInstanceInterceptor.setProperty(serviceResponse, "containers", Transform.map(new Unary<Object, ServiceContainer>() {
      public ServiceContainer f(Object item) {
        return createServiceContainer(item, config.getVersion(item));
      }
    }, instances));
    return serviceResponse;
  }

  public ServiceContainer createServiceContainer(Object instance, Integer version) {
    ServiceContainer serviceContainer = (ServiceContainer) GeneratedClassFactory.newInstance(serviceContainerClass);
    // Fill the ServiceContainer methods
    GeneratedInstanceInterceptor.setProperty(serviceContainer, "instance", instance);
    GeneratedInstanceInterceptor.setProperty(serviceContainer, "version", version);
    // Create a getter for ServiceContainer implementors (e.g. getWeatherReport() for the WeatherReport class)
    // A strongly-typed method like this is needed by SOAP clients, otherwise getInstance() would suffice.
    GeneratedInstanceInterceptor.setProperty(serviceContainer, clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1), instance);
    return serviceContainer;
  }


  private void validateNonNull(final Collection<Object> collection) {
    if (Filter.isMatch(new Filter.NullPredicate<Object>(), collection)) {
      String ids = Amass.joinByToString(new Joiner.ConcatStrings<String>(", "),
        Transform.map(new Unary<Object, String>() {
          public String f(Object item) {
            return item != null ? config.getId(item).toString() : "null";
          }
        }, collection));
      throw new HiveRuntimeException(String.format("Encountered null items in collection: %s", ids));
    }
  }

  public ServiceResponse findByProperty(String propertyName, Object value) {
    return formulateResponse(dao.findByProperty(propertyName, value));
  }

  public ServiceResponse findByPropertyRange(String propertyName, Object start, Object end) {
    return formulateResponse(dao.findByPropertyRange(propertyName, start, end));
  }

  public ServiceResponse findByPropertyRange(String propertyName, Object start, Object end, Integer firstResult, Integer maxResults) {
    return formulateResponse(dao.findByPropertyRange(propertyName, start, end, firstResult, maxResults));
  }

  public Integer getCountByPropertyRange(String propertyName, Object start, Object end) {
    return dao.getCountByRange(propertyName, start, end);
  }

  public ServiceResponse findByPropertyPaged(String propertyName, Object value, Integer firstResult, Integer maxResults) {
    return formulateResponse(dao.findByProperty(propertyName, value, firstResult, maxResults));
  }

  public ServiceResponse findByProperties(String partitioningProperty, Map<String, Object> propertyNameValueMap, Integer firstResult, Integer maxResults) {
    return formulateResponse(dao.findByProperties(partitioningProperty, propertyNameValueMap, firstResult, maxResults));
  }

  public Integer getCountByProperty(String propertyName, Object propertyValue) {
    return dao.getCount(propertyName, propertyValue);
  }

  public Integer getCountByProperties(String partitioningProperty, Map<String, Object> propertyNameValueMap, Integer firstResult, Integer maxResults) {
    return dao.getCountByProperties(partitioningProperty, propertyNameValueMap, firstResult, maxResults);
  }

  public Integer getCountByRange(String propertyName, Object minValue, Object maxValue) {
    return dao.getCountByRange(propertyName, minValue, maxValue);
  }

  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    Object retValFromSuper = null;
    try {
      if (!Modifier.isAbstract(method.getModifiers())) {
        retValFromSuper = proxy.invokeSuper(obj, args);
      }
    }
    finally {
    }

    String name = method.getName();
    if (name.equals("get"))
      return get(args[0]);
    else if (name.equals("exists"))
      return exists(args[0]);
    else if (name.equals("save"))
      return save(args[0]);
    else if (name.equals("saveAll")) {
      return saveAll(Arrays.asList((Object[]) args[0]));
    } else if (name.equals("delete"))
      return delete(args[0]);
    else if (name.equals("getPersistedClass"))
      return getPersistedClass();
    else if (method.getDeclaringClass().equals(serviceClass))
      return makeGeneralizedCall(obj, method, args);
    return retValFromSuper;
  }

  private Object makeGeneralizedCall(Object obj, final Method method, final Object[] args) {

    Collection<Entry<String, Object>> entries = null;
    IndexParamPairs indexParamPairs = AnnotationHelper.getAnnotationDeeply(method, IndexParamPairs.class);
    if (indexParamPairs != null) {
      // Collect method parameters pairs that represent an EntityIndexConfig property name and corresponding value
      int[] ints = indexParamPairs.value(); // java array stupidity
      Integer[] pairs = new Integer[ints.length];
      for (int i : ints)
        pairs[i] = i;

      entries = Transform.map(new Unary<Entry<Integer, Integer>, Entry<String, Object>>() {
        public Entry<String, Object> f(Entry<Integer, Integer> indexPair) {
          String property = ((String) args[indexPair.getKey()]);
          Object value = PrimitiveUtils.parseString(
            config.getEntityIndexConfig(property).getIndexClass(),
            (String) args[indexPair.getValue()]);
          return new Pair<String, Object>(property, value);
        }
      }, new PairIterator<Integer>(Arrays.asList(pairs)));
    } else {
      // Collect method parameters that represent and EntityIndexConfig property value
      entries = Transform.map(new Unary<Integer, Entry<String, Object>>() {
        public Entry<String, Object> f(Integer index) {
          IndexParam annotation = AnnotationHelper.getMethodArgumentAnnotationDeeply(method, index - 1, IndexParam.class);
          return new Pair<String, Object>(config.getEntityIndexConfig(((IndexParam) annotation).value()).getPropertyName(), args[index - 1]);
        }
      }, Filter.grep(new Predicate<Integer>() {
        public boolean f(Integer index) {
          return AnnotationHelper.getMethodArgumentAnnotationDeeply(method, index - 1, IndexParam.class) != null;
        }
      }, new NumberIterator(args.length)));
    }
    IndexParamPagingPair indexParamPagingPair = AnnotationHelper.getAnnotationDeeply(method, IndexParamPagingPair.class);
    Entry<Integer, Integer> pagingPair = new Pair<Integer, Integer>(0, 0);
    if (indexParamPagingPair != null) {
      // Collect method parameters pairs that represent an EntityIndexConfig property name and corresponding value
      pagingPair = new Pair<Integer, Integer>(
        (Integer) args[indexParamPagingPair.startIndexIndex()],
        (Integer) args[indexParamPagingPair.maxResultsIndex()]);
    }


    if (entries.size() == 1) {
      Entry<String, Object> entry = Atom.getFirstOrThrow(entries);
      if (method.getName().equals("getCountByProperty"))
        return getCountByProperty(entry.getKey(), entry.getValue());
      else if (method.getName().equals("findByProperty"))
        return findByProperty(entry.getKey(), entry.getValue());
    }
    if (entries.size() == 2) {
      Entry<String, Object> entry1 = Atom.getFirstOrThrow(entries);
      Entry<String, Object> entry2 = Atom.getFirstOrThrow(Atom.getRestOrThrow(entries));
      if (entry1.getKey().equals(entry2.getKey())) {
        if (method.getName().startsWith("getCountBy")) {
          return getCountByPropertyRange(entry1.getKey(), entry1.getValue(), entry2.getValue());
        }
        return indexParamPagingPair != null ?
          findByPropertyRange(entry1.getKey(), entry1.getValue(), entry2.getValue(), pagingPair.getKey(), pagingPair.getValue()) :
          findByPropertyRange(entry1.getKey(), entry1.getValue(), entry2.getValue());
      }
    }
    if (method.getName().startsWith("getCountBy") && method.getName().endsWith("Properties")) {
      return this.getCountByProperties(Atom.getFirstOrThrow(entries).getKey(), Transform.toOrderedMap(entries), pagingPair.getKey(), pagingPair.getValue());
    }
    // TODO assumes the first parameter is the partitioning parameter. Use the annotation to specify
    return findByProperties(Atom.getFirstOrThrow(entries).getKey(), Transform.toOrderedMap(entries), pagingPair.getKey(), pagingPair.getValue());
  }
}
TOP

Related Classes of org.hivedb.util.classgen.GeneratedServiceInterceptor

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.