Package controllers.elasticsearch

Source Code of controllers.elasticsearch.ElasticSearchController$ObjectType$ObjectField

/**
* Copyright 2011 The Apache Software Foundation
*
* 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.
*
* @author Felipe Oliveira (http://mashup.fm)
*
*/
package controllers.elasticsearch;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.wildcardQuery;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import play.Play;
import play.data.validation.MaxSize;
import play.data.validation.Password;
import play.data.validation.Required;
import play.db.Model;
import play.exceptions.TemplateNotFoundException;
import play.modules.elasticsearch.ElasticSearch;
import play.modules.elasticsearch.Query;
import play.modules.elasticsearch.search.SearchResults;
import play.mvc.Before;
import play.mvc.Controller;
import play.mvc.Router;

/**
* The Class ElasticSearchController.
*/
public class ElasticSearchController extends Controller {

  /**
   * Adds the type.
   *
   * @throws Exception the exception
   */
  @Before
  public static void addType() throws Exception {
    ObjectType type = ObjectType.get(getControllerClass());
    if (type == null) {
      throw new RuntimeException("Please define class for search interface with");
    }
    renderArgs.put("type", type);
  }

  /**
   * Index.
   */
  public static void index() {
    if (getControllerClass() == ElasticSearchController.class) {
      forbidden();
    }
    render("ELASTIC_SEARCH/index.html");
  }

  /**
   * Search.
   *
   * @param page the page
   * @param search the search
   * @param searchFields the search fields
   * @param orderBy the order by
   * @param order the order
   */
  public static void search(int page, String search, String searchFields, String orderBy, String order) {
    ObjectType type = ObjectType.get(getControllerClass());
    notFoundIfNull(type);
    if (page < 1) {
      page = 1;
    }
    SearchResults<Model> results = type.findPage(page, search, searchFields, orderBy, order, (String) request.args.get("where"));
    List<Model> objects = results.objects;
    Long count = results.totalCount;
    Long totalCount = type.count(null, null, (String) request.args.get("where"));
    try {
      render(type, objects, count, totalCount, page, orderBy, order);
    } catch (TemplateNotFoundException e) {
      render("ELASTIC_SEARCH/search.html", type, objects, count, totalCount, page, orderBy, order);
    }
  }

  /**
   * Show.
   *
   * @param id the id
   */
  public static void show(String id) {
    ObjectType type = ObjectType.get(getControllerClass());
    notFoundIfNull(type);
    Model object = type.findById(id);
    notFoundIfNull(object);
    try {
      render(type, object);
    } catch (TemplateNotFoundException e) {
      render("ELASTIC_SEARCH/show.html", type, object);
    }
  }

  // ~~~~~~~~~~~~~
  /**
   * The Interface For.
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface For {

    /**
     * Value.
     *
     * @return the class<? extends model>
     */
    Class<? extends Model> value();
  }

  /**
   * The Interface Exclude.
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public @interface Exclude {
  }

  /**
   * The Interface Hidden.
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public @interface Hidden {
  }

  // ~~~~~~~~~~~~~
  /**
   * Gets the page size.
   *
   * @return the page size
   */
  static int getPageSize() {
    return Integer.parseInt(Play.configuration.getProperty("elasticsearch.mashup.pageSize", "30"));
  }

  /**
   * The Class ObjectType.
   */
  public static class ObjectType implements Comparable<ObjectType> {

    /** The controller class. */
    public Class<? extends Controller> controllerClass;

    /** The entity class. */
    public Class<? extends Model> entityClass;

    /** The name. */
    public String name;

    /** The model name. */
    public String modelName;

    /** The controller name. */
    public String controllerName;

    /** The key name. */
    public String keyName;

    /**
     * Instantiates a new object type.
     *
     * @param modelClass the model class
     */
    public ObjectType(Class<? extends Model> modelClass) {
      modelName = modelClass.getSimpleName();
      entityClass = modelClass;
      keyName = Model.Manager.factoryFor(entityClass).keyName();
    }

    /**
     * Instantiates a new object type.
     *
     * @param modelClass the model class
     * @throws ClassNotFoundException the class not found exception
     */
    @SuppressWarnings("unchecked")
    public ObjectType(String modelClass) throws ClassNotFoundException {
      this((Class<? extends Model>) Play.classloader.loadClass(modelClass));
    }

    /**
     * For class.
     *
     * @param modelClass the model class
     * @return the object type
     * @throws ClassNotFoundException the class not found exception
     */
    public static ObjectType forClass(String modelClass) throws ClassNotFoundException {
      return new ObjectType(modelClass);
    }

    /**
     * Gets the.
     *
     * @param controllerClass the controller class
     * @return the object type
     */
    public static ObjectType get(Class<? extends Controller> controllerClass) {
      Class<? extends Model> entityClass = getEntityClassForController(controllerClass);
      if (entityClass == null || !Model.class.isAssignableFrom(entityClass)) {
        return null;
      }
      ObjectType type = new ObjectType(entityClass);
      type.name = getName(controllerClass.getSimpleName().replace("$", ""));
      type.controllerName = controllerClass.getSimpleName().toLowerCase().replace("$", "");
      type.controllerClass = controllerClass;
      return type;
    }

    /**
     * Gets the name.
     *
     * @param name the name
     * @return the name
     */
    private static String getName(String name) {
      StringBuilder sb = new StringBuilder();
      int count = 0;
      for (char c : name.toCharArray()) {
        count++;
        if (count == 1) {
          sb.append(String.valueOf(c).toUpperCase());

        } else {
          if (Character.isUpperCase(c)) {
            sb.append(" ");
          }
          sb.append(c);
        }
      }
      return sb.toString();
    }

    /**
     * Gets the entity class for controller.
     *
     * @param controllerClass the controller class
     * @return the entity class for controller
     */
    @SuppressWarnings("unchecked")
    public static Class<? extends Model> getEntityClassForController(Class<? extends Controller> controllerClass) {
      if (controllerClass.isAnnotationPresent(For.class)) {
        return ((controllerClass.getAnnotation(For.class))).value();
      }
      for (Type it : controllerClass.getGenericInterfaces()) {
        if (it instanceof ParameterizedType) {
          ParameterizedType type = (ParameterizedType) it;
          if (((Class<?>) type.getRawType()).getSimpleName().equals("ELASTIC_SEARCHWrapper")) {
            return (Class<? extends Model>) type.getActualTypeArguments()[0];
          }
        }
      }
      String name = controllerClass.getSimpleName().replace("$", "");
      name = "models." + name.substring(0, name.length() - 1);
      try {
        return (Class<? extends Model>) Play.classloader.loadClass(name);
      } catch (ClassNotFoundException e) {
        return null;
      }
    }

    /**
     * Gets the list action.
     *
     * @return the list action
     */
    public Object getListAction() {
      return Router.reverse(controllerClass.getName().replace("$", "") + ".list");
    }

    /**
     * Gets the blank action.
     *
     * @return the blank action
     */
    public Object getBlankAction() {
      return Router.reverse(controllerClass.getName().replace("$", "") + ".blank");
    }
   
    /**
     * Builds a query which searches ES with the given search criteria
     *
     * @param search the search
     * @param searchFields the searchfields
     * @param where the where
     * @return the builder
     */
    private BoolQueryBuilder buildQueryBuilder(String search, String searchFields, String where) {
      BoolQueryBuilder qb = boolQuery();

      if(search == null || search.isEmpty()) {
        qb.must(QueryBuilders.matchAllQuery());
      } else {
        // FIXME Currently we search in all fields and ignore searchFields
        qb.must(wildcardQuery("_all", "*" + search + "*"));
      }
     
      return qb;
    }

    /**
     * Count.
     *
     * @param search the search
     * @param searchFields the search fields
     * @param where the where
     * @return the long
     */
    public Long count(String search, String searchFields, String where) {
      BoolQueryBuilder qb = buildQueryBuilder(search, searchFields, where);     
      Query<?> query = ElasticSearch.query(qb, entityClass);
      query.from(0).size(0);
      SearchResults<?> result = query.fetch();
     
      return result.totalCount;
    }

    /**
     * Find page.
     *
     * @param page the page
     * @param search the search
     * @param searchFields the search fields
     * @param orderBy the order by
     * @param order the order
     * @param where the where
     * @return the list
     */
    @SuppressWarnings("unchecked")
    public <M extends Model> SearchResults<M> findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
      BoolQueryBuilder qb = buildQueryBuilder(search, searchFields, where);     
      Query<M> query = (Query<M>) ElasticSearch.query(qb, entityClass);
      // FIXME Currently we ignore the orderBy and order fields
      query.from((page - 1) * getPageSize()).size(getPageSize());
      query.hydrate(true);
     
      return query.fetch();
    }

    /**
     * Find by id.
     *
     * @param id the id
     * @return the model
     */
    public Model findById(Object id) {
      if (id == null) {
        return null;
      }
      return Model.Manager.factoryFor(entityClass).findById(id);
    }

    /**
     * Gets the fields.
     *
     * @return the fields
     */
    public List<ObjectField> getFields() {
      List<ObjectField> fields = new ArrayList<ObjectField>();
      for (Model.Property f : Model.Manager.factoryFor(entityClass).listProperties()) {
        ObjectField of = new ObjectField(f);
        if (of.type != null) {
          fields.add(of);
        }
      }
      return fields;
    }

    /**
     * Gets the field.
     *
     * @param name the name
     * @return the field
     */
    public ObjectField getField(String name) {
      for (ObjectField field : getFields()) {
        if (field.name.equals(name)) {
          return field;
        }
      }
      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(ObjectType other) {
      return modelName.compareTo(other.modelName);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
      return modelName;
    }

    /**
     * The Class ObjectField.
     */
    public static class ObjectField {

      /** The property. */
      private Model.Property property;

      /** The type. */
      public String type = "unknown";

      /** The name. */
      public String name;

      /** The multiple. */
      public boolean multiple;

      /** The required. */
      public boolean required;

      /**
       * Instantiates a new object field.
       *
       * @param property the property
       */
      public ObjectField(Model.Property property) {
        Field field = property.field;
        this.property = property;
        if (CharSequence.class.isAssignableFrom(field.getType())) {
          type = "text";
          if (field.isAnnotationPresent(MaxSize.class)) {
            int maxSize = field.getAnnotation(MaxSize.class).value();
            if (maxSize > 100) {
              type = "longtext";
            }
          }
          if (field.isAnnotationPresent(Password.class)) {
            type = "password";
          }
        }
        if (Number.class.isAssignableFrom(field.getType()) || field.getType().equals(double.class) || field.getType().equals(int.class) || field.getType().equals(long.class)) {
          type = "number";
        }
        if (Boolean.class.isAssignableFrom(field.getType()) || field.getType().equals(boolean.class)) {
          type = "boolean";
        }
        if (Date.class.isAssignableFrom(field.getType())) {
          type = "date";
        }
        if (property.isRelation) {
          type = "relation";
        }
        if (property.isMultiple) {
          multiple = true;
        }
        if (field.getType().isEnum()) {
          type = "enum";
        }
        if (property.isGenerated) {
          type = null;
        }
        if (field.isAnnotationPresent(Required.class)) {
          required = true;
        }
        if (field.isAnnotationPresent(Hidden.class)) {
          type = "hidden";
        }
        if (field.isAnnotationPresent(Exclude.class)) {
          type = null;
        }
        if (java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
          type = null;
        }
        name = field.getName();
      }

      /**
       * Gets the choices.
       *
       * @return the choices
       */
      public List<Object> getChoices() {
        return property.choices.list();
      }
    }
  }
}
TOP

Related Classes of controllers.elasticsearch.ElasticSearchController$ObjectType$ObjectField

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.