Package com.iisigroup.cap.dao.impl

Source Code of com.iisigroup.cap.dao.impl.GenericDao$CapSpecifications

/*
* GenericDao.java
*
* Copyright (c) 2009-2012 International Integrated System, Inc.
* 11F, No.133, Sec.4, Minsheng E. Rd., Taipei, 10574, Taiwan, R.O.C.
* All Rights Reserved.
*
* Licensed Materials - Property of International Integrated System,Inc.
*
* This software is confidential and proprietary information of
* International Integrated System, Inc. ("Confidential Information").
*/
package com.iisigroup.cap.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.iisigroup.cap.dao.IGenericDao;
import com.iisigroup.cap.dao.utils.ISearch;
import com.iisigroup.cap.dao.utils.SearchMode;
import com.iisigroup.cap.dao.utils.SearchModeParameter;
import com.iisigroup.cap.jdbc.CapNamedJdbcTemplate;
import com.iisigroup.cap.model.IDataObject;
import com.iisigroup.cap.model.Page;

/**
* <pre>
* Dao
* </pre>
*
* @since 2011/11/1
* @author rodeschen
* @version <ul>
*          <li>2011/11/1,rodeschen,new
*          <li>2011/11/20,gabriella,modify
*          <li>2012/2/14,RodesChen,add resource name
*          <li>2012/6/29,RodesChen,add findUniqueOrNone setMaxResults 1
*          <li>2013/5/21,增加SearchMode or & and 的查詢設定
*          </ul>
* @param <T>
*/
public class GenericDao<T> implements IGenericDao<T> {

  protected Class<T> type;
  protected Logger logger;

  @PersistenceContext
  private EntityManager entityManager;
 
  @Resource(name = "capJdbcTemplate")
  private CapNamedJdbcTemplate namedJdbcTemplate;

  @SuppressWarnings("unchecked")
  public GenericDao() {
    try {
      type = (Class<T>) ((ParameterizedType) getClass()
          .getGenericSuperclass()).getActualTypeArguments()[0];
    } catch (ClassCastException e) {
      Class<T> clazz = (Class<T>) getClass().getGenericSuperclass();
      type = (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass())
          .getActualTypeArguments()[0];
    }
    logger = LoggerFactory.getLogger(getClass());
  }// ;

  /**
   * Insert.
   *
   * @param entity
   *            the entry
   */
  public void save(Object entity) {
    Assert.notNull(entity, "The entity to save cannot be null element");
    if (!getEntityManager().contains(entity)) {
      getEntityManager().persist(entity);
    }
  }// ;

  public void save(List<?> entries) {
    for (Object entity : entries) {
      Assert.notNull(entity, "The List must not contain null element");
      save(entity);
    }
  }// ;

  public void merge(T entity) {
    Assert.notNull(entity, "The entity to save cannot be null element");
    getEntityManager().merge(entity);
  }// ;

  /**
   * Delete.
   *
   * @param entity
   *            the entry
   */
  public void delete(Object entity) {
    if (getEntityManager().contains(entity)) {
      getEntityManager().remove(entity);
    } else {
      // could be a delete on a transient instance
      T entityRef = getEntityManager().getReference(type,
          getPrimaryKey(entity));

      if (entityRef != null) {
        getEntityManager().remove(entityRef);
      }
    }
  }// ;

  public void delete(List<?> entries) {
    for (Object entity : entries) {
      delete(entity);
    }
  }// ;

  /**
   * Find.
   *
   * @param pk
   *            the oid
   *
   * @return the t
   */
  public T find(Serializable pk) {
    return getEntityManager().find(type, pk);
  }// ;

  public Serializable getPrimaryKey(Object model) {
    if (model instanceof IDataObject) {
      return (Serializable) ((IDataObject) model).getOid();
    } else {
      return null;
    }
  }

  public T find(T entity) {
    Serializable pk = getPrimaryKey(entity);
    if (pk == null) {
      return null;
    }
    return (T) getEntityManager().find(type, pk);
  }// ;

  public T findUniqueOrNone(ISearch search) {
    search.setFirstResult(0).setMaxResults(1);
    List<T> models = find(getType(), search);
    if (models != null && !models.isEmpty()) {
      return models.iterator().next();
    }
    return null;
  }// ;

  public Iterator<T> list(int first, int count) {
    ISearch search = createSearchTemplete();
    search.setFirstResult(first).setMaxResults(count);
    return createQuery(getType(), search).getResultList().iterator();
  }// ;

  @Override
  public int count(ISearch search) {
    return count(getType(), search);
  }

  public List<T> find(final ISearch search) {
    return createQuery(getType(), search).getResultList();
  }// ;

  /**
   * 查詢頁的資料
   *
   * @param search
   *            SearchSetting
   * @return Page<S>
   */
  public Page<T> findPage(ISearch search) {
    return findPage(getType(), search);
  }// ;

  /**
   * find by SearchSetting
   *
   * @param <S>
   *            bean
   * @param search
   *            SearchSetting
   * @param clazz
   *            Class<S>
   * @return List<S>
   */
  public <S> List<S> find(Class<S> clazz, final ISearch search) {
    return createQuery(clazz, search).getResultList();
  }// ;

  /**
   * 取得筆數
   *
   * @param <S>
   *            bean
   * @param clazz
   *            Class<S>
   * @param search
   *            SearchSetting
   * @return int
   */
  public <S> int count(Class<S> clazz, ISearch search) {
    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<Long> query = builder.createQuery(Long.class);
    Root<S> root = query.from(clazz);
    query = applySpecificationToCriteria(root, query, builder, search);
    query.select(builder.count(root));
    Long count = getEntityManager().createQuery(query).getSingleResult();
    return count.intValue();
  }// ;

  /**
   * 查詢頁的資料
   *
   * @param <S>
   *            bean
   * @param clazz
   *            Class<S>
   * @param search
   *            SearchSetting
   * @return Page<S>
   */
  public <S> Page<S> findPage(Class<S> clazz, ISearch search) {
    return new Page<S>(find(clazz, search), count(clazz, search),
        search.getMaxResults(), search.getFirstResult());
  }// ;

  protected <S> TypedQuery<S> createQuery(Class<S> clazz, ISearch search) {
    ISearch thisSearch = (search != null) ? search : createSearchTemplete();
    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<S> query = builder.createQuery(clazz);
    Root<S> root = query.from(clazz);

    query = applySpecificationToCriteria(root, query, builder, thisSearch);
    TypedQuery<S> tquery = applyPaginationAndOrderToCriteria(root, query,
        builder, thisSearch);
    return tquery;
  }// ;

  protected TypedQuery<T> createQuery(ISearch search) {
    ISearch thisSearch = (search != null) ? search : createSearchTemplete();
    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<T> query = builder.createQuery(getType());
    Root<T> root = query.from(getType());

    query = applySpecificationToCriteria(root, query, builder, thisSearch);
    TypedQuery<T> tquery = applyPaginationAndOrderToCriteria(root, query,
        builder, thisSearch);
    return tquery;
  }// ;

  /**
   * 設定查詢條件
   *
   * @param <S>
   * @param root
   *            Root
   * @param query
   *            CriteriaQuery
   * @param builder
   *            CriteriaBuilder
   * @param search
   *            SearchSetting
   * @return CriteriaQuery
   */
  @SuppressWarnings({ "rawtypes" })
  protected <S> CriteriaQuery<S> applySpecificationToCriteria(Root root,
      CriteriaQuery<S> query, CriteriaBuilder builder, ISearch search) {
    if (search.getSearchModeParameters() != null) {
      Predicate[] aryWhere = new Predicate[search
          .getSearchModeParameters().size()];
      int i = 0;
      for (SearchModeParameter param : search.getSearchModeParameters()) {
        CapSpecifications spec = new CapSpecifications(param);
        aryWhere[i++] = spec.toPredicate(root, query, builder);
      }
      query.where(builder.and(aryWhere));
    }

    return query;
  }// ;

  /**
   * 設定查詢筆數及欄位排列順序
   *
   * @param root
   *            Root
   * @param query
   *            CriteriaQuery
   * @param builder
   *            CriteriaBuilder
   * @param search
   *            SearchSetting
   * @return TypedQuery
   */
  protected <S> TypedQuery<S> applyPaginationAndOrderToCriteria(Root<S> root,
      CriteriaQuery<S> query, CriteriaBuilder builder, ISearch search) {
    // set order criteria if available
    if (search.hasOrderBy()) {

      Map<String, Boolean> orderMap = search.getOrderBy();
      List<Order> orders = new ArrayList<Order>();
      // int i = 0;
      for (Entry<String, Boolean> entry : orderMap.entrySet()) {
        Expression<?> expression = null;
        String[] pathElements = entry.getKey().split("\\.");
        int pathSize = pathElements.length;
        if (pathSize > 1) {
          Path<?> path = root.get(pathElements[0]);
          for (int i = 1; i <= pathElements.length - 1; i++) {
            Join join = root.join(pathElements[i-1]);
            path = join.get(pathElements[i]);
          }
          expression = path;
        } else {
          expression = root.get(entry.getKey());
        }
        orders.add((entry.getValue()) ? builder.desc(expression)
            : builder.asc(expression));

      }
      query.orderBy(orders);
    }
    TypedQuery<S> tQuery = getEntityManager().createQuery(query);
    if (search != null) {
      // set pagination if needed
      tQuery.setFirstResult(search.getFirstResult());
      tQuery.setMaxResults(search.getMaxResults());
    }
    return tQuery;
  }// ;

  // -------------------------------------------------------
  /**
   * <pre>
   * CapSpecifications
   * </pre>
   */
  @SuppressWarnings("rawtypes")
  class CapSpecifications {

    private SearchMode _searchMode;
    private Object _key;
    private Object _value;

    SearchModeParameter param;

    CapSpecifications(SearchModeParameter param) {
      this._searchMode = param.getMode();
      this._key = param.getKey();
      this._value = param.getValue();
    }

    @SuppressWarnings({ "unchecked", "incomplete-switch" })
    public Predicate toPredicate(Root root, CriteriaQuery query,
        CriteriaBuilder builder) {
      try {
        if (_key instanceof SearchModeParameter
            && _value instanceof SearchModeParameter) {
          CapSpecifications spec_key = new CapSpecifications(
              (SearchModeParameter) _key);
          CapSpecifications spec_value = new CapSpecifications(
              (SearchModeParameter) _value);
          if (SearchMode.OR == _searchMode) {
            return builder.or(
                spec_key.toPredicate(root, query, builder),
                spec_value.toPredicate(root, query, builder));
          } else if (SearchMode.AND == _searchMode) {
            return builder.and(
                spec_key.toPredicate(root, query, builder),
                spec_value.toPredicate(root, query, builder));
          } else {
            return null;
          }
        } else if (SearchMode.OR == _key || SearchMode.AND == _key) {
          List<SearchModeParameter> list = (List<SearchModeParameter>) _value;
          List<Predicate> predicates = new ArrayList<Predicate>(
              list.size());
          for (SearchModeParameter param : list) {
            predicates.add(new CapSpecifications(param)
                .toPredicate(root, query, builder));
          }
          if (SearchMode.OR == _key) {
            return builder.or(predicates
                .toArray(new Predicate[predicates.size()]));
          } else {
            return builder.and(predicates
                .toArray(new Predicate[predicates.size()]));
          }
        }
        String key = (String) _key;

        String[] pathElements = key.split("\\.");

        boolean needJoin = false;
        Join join = null;
        if (pathElements.length > 1) {
            join = root.join(pathElements[0]);
            needJoin = true;
        }
        Path<?> path = root.get(pathElements[0]);
        for (int i = 1; i <= pathElements.length - 1; i++) {
            if (needJoin) {
                if (i == pathElements.length - 1) {
                    path = join.get(pathElements[i]);
                } else {
                    join = join.join(pathElements[i]);
                }
            } else {
                path = path.get(pathElements[i]);
            }
        }

        switch (_searchMode) {

        case BETWEEN:
          Object[] values = asArray(_value);
          if (values != null) {
            return builder.between((Path<Comparable>) path,
                asComparable(values[0]),
                asComparable(values[1]));
          } else {
            return null;
          }
        case GREATER_THAN:
          return builder.greaterThan((Path<Comparable>) path,
              asComparable(_value));
        case GREATER_EQUALS:
          return builder.greaterThanOrEqualTo(
              (Path<Comparable>) path, asComparable(_value));
        case LESS_THAN:
          return builder.lessThan((Path<Comparable>) path,
              asComparable(_value));
        case LESS_EQUALS:
          return builder.lessThanOrEqualTo((Path<Comparable>) path,
              asComparable(_value));
        case IS_NULL:
          return builder.isNull(path);
        case IS_NOT_NULL:
          return builder.isNotNull(path);
        case IN:
          return path.in(asArray(_value));
        case NOT_IN:
          return builder.not(path.in(asArray(_value)));
        case LIKE:
          return builder.like((Path<String>) path,
              String.valueOf(_value));
        case NOT_LIKE:
          return builder.notLike((Path<String>) path,
              String.valueOf(_value));
        case EQUALS:
          return builder.equal(path, _value);
        case NOT_EQUALS:
          return builder.notEqual(path, _value);
        }
      } catch (Exception e) {
        logger.error(e.getLocalizedMessage(), e);
      }
      return null;
    }

    private Comparable asComparable(Object value) {
      if (value instanceof Comparable) {
        return (Comparable<?>) value;
      } else {
        return null;
      }
    }

    @SuppressWarnings("unused")
    private Collection<?> asCollection(Object value) {
      if (value instanceof Collection) {
        return (Collection<?>) value;
      } else if (value.getClass().isArray()) {
        return Arrays.asList(value);
      }
      return Arrays.asList(value);
    }

    private Object[] asArray(Object value) {
      if (value.getClass().isArray()) {
        Object[] result = new Object[Array.getLength(value)];
        for (int i = 0; i < result.length; ++i) {
          result[i] = Array.get(value, i);
        }
        return result;
      } else if (value instanceof Collection) {
        return ((Collection) value).toArray();
      }
      return null;
    }
  }

  public Class<T> getType() {
    return type;
  }

  @SuppressWarnings("rawtypes")
  public GenericDao setType(Class<T> type) {
    this.type = type;
    return this;
  }

  public ISearch createSearchTemplete() {
    return new SearchSetting();
  }

  public void flush() {
    getEntityManager().flush();
    getEntityManager().clear();
  }

  public <S> S findById(Class<S> clazz, Serializable pk) {
    return getEntityManager().find(clazz, pk);
  }

  protected EntityManager getEntityManager() {
    return entityManager;
  }

  protected CapNamedJdbcTemplate getNamedJdbcTemplate() {
    return namedJdbcTemplate;
  }

}
TOP

Related Classes of com.iisigroup.cap.dao.impl.GenericDao$CapSpecifications

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.