Package play.modules.elasticsearch.mapping.impl

Source Code of play.modules.elasticsearch.mapping.impl.PlayModelMapper

package play.modules.elasticsearch.mapping.impl;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.elasticsearch.common.xcontent.XContentBuilder;

import play.db.Model;
import play.modules.elasticsearch.annotations.ElasticSearchIgnore;
import play.modules.elasticsearch.annotations.ElasticSearchTtl;
import play.modules.elasticsearch.annotations.ElasticSearchable;
import play.modules.elasticsearch.annotations.analysis.ElasticSearchAnalysis;
import play.modules.elasticsearch.annotations.analysis.ElasticSearchAnalyzer;
import play.modules.elasticsearch.annotations.analysis.ElasticSearchFilter;
import play.modules.elasticsearch.annotations.analysis.ElasticSearchSetting;
import play.modules.elasticsearch.mapping.FieldMapper;
import play.modules.elasticsearch.mapping.MapperFactory;
import play.modules.elasticsearch.mapping.ModelMapper;
import play.modules.elasticsearch.util.ReflectionUtil;

/**
* ModelMapper for play.db.Model subclasses.
*
* @param <M>
*            the model type
*/
public class PlayModelMapper<M extends Model> implements ModelMapper<M> {

  /** The play-specific fields to ignore. */
  private static List<String> IGNORE_FIELDS = new ArrayList<String>();
  static {
    IGNORE_FIELDS.add("avoidCascadeSaveLoops");
    IGNORE_FIELDS.add("willBeSaved");
    IGNORE_FIELDS.add("serialVersionId");
    IGNORE_FIELDS.add("serialVersionUID");
  }

  private final Class<M> clazz;
  private final ElasticSearchable meta;
  private final List<FieldMapper<M>> mapping;

  public PlayModelMapper(MapperFactory factory, Class<M> clazz) {
    Validate.notNull(clazz, "Clazz cannot be null");
    this.clazz = clazz;
    this.meta = clazz.getAnnotation(ElasticSearchable.class);

    // Create mapping
    mapping = getMapping(factory, clazz);
  }

  static boolean shouldIgnoreField(Field field) {
    String name = field.getName();

    return StringUtils.isBlank(name) || IGNORE_FIELDS.contains(name)
        || shouldIgnoreJPAField(field);
  }

  /**
   * Checks if a field should be ignored based on JPA-specifics
   *
   * @param field
   *            the field to check
   * @return true if the field should be ignored, false otherwise
   */
  static boolean shouldIgnoreJPAField(Field field) {
    return field.isAnnotationPresent(Transient.class);
  }

  static boolean userRequestedIgnoreField(Field field) {
    return field.isAnnotationPresent(ElasticSearchIgnore.class);
  }

  /**
   * Gets a list of {@link FieldMapper}s for the given model class
   *
   * @param <M>
   *            the model type
   * @param factory
   *            the mapper factory
   * @param clazz
   *            the model class
   * @return the list of FieldMappers
   */
  private static final <M extends Model> List<FieldMapper<M>> getMapping(MapperFactory factory,
      Class<M> clazz) {
    List<FieldMapper<M>> mapping = new ArrayList<FieldMapper<M>>();

    List<Field> indexableFields = ReflectionUtil.getAllFields(clazz);

    for (Field field : indexableFields) {

      // Exclude fields on our ignore list
      if (shouldIgnoreField(field) || userRequestedIgnoreField(field)) {
        continue;
      }

      FieldMapper<M> mapper = factory.getMapper(field);
      mapping.add(mapper);
    }

    return mapping;
  }

  @Override
  public Class<M> getModelClass() {
    return clazz;
  }

  @Override
  public String getIndexName() {
    if (meta.indexName().length() > 0) {
      return meta.indexName();
    } else {
      return getTypeName();
    }
  }

  @Override
  public String getTypeName() {
    return clazz.getName().toLowerCase().trim().replace('.', '_');
  }

  @Override
  public String getDocumentId(M model) {
    return String.valueOf(model._key());
  }

  @Override
  public void addMapping(XContentBuilder builder) throws IOException {
    builder.startObject(getTypeName());
    if (clazz.isAnnotationPresent(ElasticSearchTtl.class)) {
      String ttlValue = clazz.getAnnotation(ElasticSearchTtl.class).value();
      builder.startObject("_ttl");
      builder.field("enabled", true);
      builder.field("default", ttlValue);
      builder.endObject();
    }
   
    builder.startObject("properties");

    for (FieldMapper<M> field : mapping) {
      field.addToMapping(builder);
    }

    builder.endObject();
    builder.endObject();
  }
 
  public void addSettings(XContentBuilder builder) throws IOException{

    if(clazz.getAnnotation(ElasticSearchable.class).analysis() == null)
      return;

    ElasticSearchAnalysis analysis = clazz.getAnnotation(ElasticSearchable.class).analysis();
   
    if((analysis.analyzers() == null || analysis.analyzers().length < 1) &&
       (analysis.filters() == null || analysis.filters().length < 1))
      return;
   
    builder.startObject("analysis");
   
    if(analysis.analyzers() != null && analysis.analyzers().length > 0){
      builder.startObject("analyzer");

      for (ElasticSearchAnalyzer analyzer : analysis.analyzers()) {
       
        builder.startObject(analyzer.name());
       
        if(analyzer.tokenizer() != null)
          builder.field("tokenizer", analyzer.tokenizer());
       
        if(analyzer.filtersNames() != null && analyzer.filtersNames().length > 0)
          builder.field("filter", analyzer.filtersNames());
       
        builder.endObject();
      }
     
      builder.endObject();
    }
   
    if(analysis.filters() != null && analysis.filters().length > 0){
     
      builder.startObject("filter");
   
      for (ElasticSearchFilter filter : analysis.filters()) {
       
        builder.startObject(filter.name());
       
        builder.field("type", filter.typeName());
       
        for (ElasticSearchSetting setting : filter.settings()) {
         
          builder.field(setting.name(), setting.value());
         
        }
       
        builder.endObject();
      }
     
      builder.endObject();
    }
   
    builder.endObject();
  }

  @Override
  public void addModel(M model, XContentBuilder builder) throws IOException {
    builder.startObject();

    for (FieldMapper<M> field : mapping) {
      field.addToDocument(model, builder);
    }

    builder.endObject();
  }

  @Override
  public M createModel(Map<String, Object> map) {
    M model = ReflectionUtil.newInstance(clazz);

    for (FieldMapper<M> field : mapping) {
      field.inflate(model, map);
    }

    return model;
  }

}
TOP

Related Classes of play.modules.elasticsearch.mapping.impl.PlayModelMapper

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.