Package play.utils.meta.cp

Source Code of play.utils.meta.cp.ClasspathScanningModelRegistry

package play.utils.meta.cp;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

import play.Logger;
import play.Logger.ALogger;
import play.utils.meta.ConverterRegistry;
import play.utils.meta.FieldMetadata;
import play.utils.meta.ModelMetadata;
import play.utils.meta.ModelRegistry;
import play.utils.meta.convert.Converter;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class ClasspathScanningModelRegistry implements ModelRegistry {

  private static ALogger log = Logger.of(ClasspathScanningModelRegistry.class);
 
  private Map<Class<?>, ModelMetadata> models;
  private ConverterRegistry converters;

  public ClasspathScanningModelRegistry(ConverterRegistry converters, ClassLoader... cls) {
    this.converters = converters;
    this.models = scan(cls);
  }

  private Map<Class<?>, ModelMetadata> scan(ClassLoader... classloaders) {
    Map<Class<?>, ModelMetadata> map = Maps.newHashMap();

    final Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(
        ClasspathHelper.forPackage("", classloaders)).setScanners(new SubTypesScanner(),
        new TypeAnnotationsScanner()).addClassLoaders(classloaders));

    Set<Class<?>> entities = reflections.getTypesAnnotatedWith(Entity.class);
    for (Class<?> entity : entities) {
      ModelMetadata metadata = getMetadata(entity);
      map.put(entity, metadata);
    }

    return map;
  }

  private ModelMetadata getMetadata(Class<?> entity) {
    if (log.isDebugEnabled())
      log.debug("getMetadata for: " + entity);
    List<Field> modelFields = Lists.newArrayList(entity.getDeclaredFields());

    Class<?> superClass = entity.getSuperclass();
    while (superClass != null
        && Iterables.tryFind(Lists.newArrayList(superClass.getAnnotations()), new Predicate<Annotation>() {
          @Override
          public boolean apply(Annotation annotation) {
            return annotation.annotationType().equals(MappedSuperclass.class);
          }
        }).isPresent()) {

      modelFields.addAll(Lists.newArrayList(superClass.getDeclaredFields()));
      superClass = superClass.getSuperclass();
    }
    if (log.isDebugEnabled())
      log.debug("superClass : " + superClass);

    Function<Field, FieldMetadata> fieldMetadata = extractFieldMetadata();
    Function<FieldMetadata, String> fieldName = extractFieldName();
    @SuppressWarnings("unchecked")
    Map<String, FieldMetadata> fields = Maps.uniqueIndex(
        Iterables.transform(
            Iterables.filter(modelFields, Predicates.<Field> and(
                Predicates.not(ReflectionUtils.withAnnotation(Transient.class)),
                Predicates.not(ReflectionUtils.withModifier(Modifier.STATIC)),
                Predicates.not(ReflectionUtils.withModifier(Modifier.FINAL)),
                Predicates.not(new Predicate<Field>() {
                  @Override
                  public boolean apply(Field field) {
                    return field.getName().startsWith("_ebean");
                  }
                }))), fieldMetadata), fieldName);
   
    if (log.isDebugEnabled()) {
      log.debug("fields : ");
      Set<String> fieldNames = fields.keySet();
      for (String fn : fieldNames) {
        log.debug(" * " + fn + " : " + fields.get(fn));
      }
    }

    Optional<FieldMetadata> keyField = Iterables.tryFind(fields.values(), new Predicate<FieldMetadata>() {
      @Override
      public boolean apply(FieldMetadata fieldInfo) {
        return fieldInfo.isKey();
      }
    });
    if (log.isDebugEnabled())
      log.debug("keyField : " + keyField);
   
    ModelMetadata metadata = null;
    if (keyField.isPresent()) {
      metadata = new ModelMetadata(entity, fields, keyField.get());
    }
    return metadata;
  }

  @Override
  public Collection<ModelMetadata> getModels() {
    return models.values();
  }

  @Override
  public <M> ModelMetadata getModel(Class<M> modelType) {
    return models.get(modelType);
  }

  private FieldMetadata toFieldMetadata(Field field) {
    Converter<?> converter = converters.getConverter(field.getType());
    return new FieldMetadata(field, converter);
  }

  private Function<Field, FieldMetadata> extractFieldMetadata() {
    return new Function<Field, FieldMetadata>() {
      @Override
      public FieldMetadata apply(Field field) {
        return toFieldMetadata(field);
      }
    };
  }

  private Function<FieldMetadata, String> extractFieldName() {
    return new Function<FieldMetadata, String>() {
      @Override
      public String apply(FieldMetadata fieldInfo) {
        return fieldInfo.getField().getName();
      }
    };
  }

  public Iterable<? extends String> getModelNames() {
    Collection<ModelMetadata> models = getModels();
    List<String> list = new ArrayList<String>();
    for (ModelMetadata model : models) {
      list.add(model.getName());
    }
    return list ;
  }

}
TOP

Related Classes of play.utils.meta.cp.ClasspathScanningModelRegistry

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.