Package org.activejpa.entity

Source Code of org.activejpa.entity.EntityCollection

/**
*
*/
package org.activejpa.entity;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;

import org.activejpa.ActiveJpaException;
import org.activejpa.util.PropertyUtil;
import org.javalite.common.Inflector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author ganeshs
*
*/
public class EntityCollection<T extends Model> extends BaseObject {
 
  private Model parent;
 
  private String name;
 
  private Class<T> elementType;
 
  private static final Logger logger = LoggerFactory.getLogger(EntityCollection.class);
 
  /**
   * @param parent
   * @param name
   */
  public EntityCollection(Model parent, String name, Class<T> elementType) {
    this.parent = parent;
    this.name = name;
    this.elementType = elementType;
  }
 
  /**
   * Adds the item to the underlying collection
   */
  public T add(T item) {
    logger.debug("Adding the item {} to the collection", item);
    return addOrRemove(item, true);
  }
 
  /**
   * Removes the item from the underlying collection
   */
  public T remove(T item) {
    logger.debug("Removing the item {} from the collection", item);
    return addOrRemove(item, false);
  }
 
  /**
   * Adds or Removes the item to/from the underlying collection. This method attempts in the following order to add/remove the item,
   * <ul>
   * <li> Checks if there's a method with the signature <code>addOrderItem(OrderItem orderItem)</code> in the parent model where orderItem is a collection.
   * <li> Retrieves the getter for the collection property and adds/removes the item to/from that
   * <li> Retrieves the collection property field and adds/removes the item to/from that
   * </ul>
   *
   * Throws {@link ActiveJpaException} if none of the above ways adds/removes the item to/from the collection
   * @param item
   */
  @SuppressWarnings("unchecked")
  protected T addOrRemove(T item, boolean add) {
    Method method = null;
    String methodName = getMethodName(add ? "add" : "remove", name);
    try {
      logger.trace("Attempting to invoke the method {} on the parent {}", methodName, parent);
      method = parent.getClass().getDeclaredMethod(methodName, elementType);
      method.invoke(parent, item);
      return item;
    } catch (NoSuchMethodException e) {
      logger.debug("Method {} doesn't exist in the class {}", methodName, parent.getClass());
    } catch (Exception e) {
      throw new ActiveJpaException("Failed while invoking the method " + method.getName(), e);
    }
   
    // Try adding the item to the collection property returned by the getter
    logger.trace("Attempting to invoke the getter for the property {} on the parent {}", name, parent);
    Collection<T> collection = (Collection<T>) PropertyUtil.getProperty(parent, name);
    if (collection != null) {
      if (add) {
        collection.add(item);
      } else {
        collection.remove(item);
      }
      return item;
    }
   
    // Try to find out the field and add/remove it to/from that
    try {
      logger.trace("Attempting to invoke the the property {} on the parent {}", name, parent);
      Field field = parent.getClass().getDeclaredField(name);
      field.setAccessible(true);
      collection = (Collection<T>) field.get(parent);
      if (add) {
        collection.add(item);
      } else {
        collection.remove(item);
      }
      return item;
    } catch (Exception e) {
      logger.error("Failed to {} the item {} to the collection of the parent", add ? "add" : "remove", item, parent);
      throw new ActiveJpaException("Failed while adding/removing the item to the collection - " + name, e);
    }
  }

  public T findById(Serializable id) {
    return one(name + ".id", id);
  }
 
  public List<T> all() {
    return where(new Filter());
  }
 
  public T first(Object... paramValues) {
    List<T> list = where(createFilter(paramValues));
    if (list == null || list.isEmpty()) {
      return null;
    }
    return list.get(0);
  }
 
  public T one(Object... paramValues) {
    Filter filter = createFilter(paramValues);
    return createCollectionQuery(filter).getSingleResult();
  }
 
  public List<T> where(Filter filter) {
    return createCollectionQuery(filter).getResultList();
  }
 
  public List<T> where(Object... paramValues) {
    return where(createFilter(paramValues));
  }
 
  public long count(Filter filter) {
    filter.addCondition("id", parent.getId());
    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<Long> cQuery = builder.createQuery(Long.class);
    Root<? extends Model> root = cQuery.from(parent.getClass());
    Join join = root.join(name);
    cQuery.select(builder.count(join));
    filter.constructQuery(builder, cQuery, root);
   
    TypedQuery<Long> query = createQuery(cQuery, filter);
    return query.getSingleResult();
  }
 
  private TypedQuery<T> createCollectionQuery(Filter filter) {
    filter.addCondition("id", parent.getId());
    TypedQuery<T> query = createQuery(parent.getClass(), name, elementType, filter);
    return query;
  }
 
  public void persist() {
    parent.persist();
  }
 
  /**
   * Constructs the name of the method from the collectionName
   *
   * @param prefix
   * @param collectionName
   * @return
   */
  private String getMethodName(String prefix, String collectionName) {
    collectionName = Inflector.singularize(collectionName);
    return prefix + collectionName.substring(0, 1).toUpperCase() + collectionName.substring(1);
  }
}
TOP

Related Classes of org.activejpa.entity.EntityCollection

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.