package com.jspxcms.core.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.jspxcms.common.orm.LimitRequest;
import com.jspxcms.common.orm.Limitable;
import com.jspxcms.common.orm.SearchFilter;
import com.jspxcms.common.util.RowSide;
import com.jspxcms.core.domain.Node;
import com.jspxcms.core.repository.NodeDao;
import com.jspxcms.core.service.NodeQueryService;
/**
* NodeQueryServiceImpl
*
* @author liufang
*
*/
@Service
@Transactional(readOnly = true)
public class NodeQueryServiceImpl implements NodeQueryService {
public List<Node> findList(Integer parentId, Boolean showDescendants,
Integer userId, boolean allNode, Map<String, String[]> params,
Sort sort) {
List<Node> list;
if (showDescendants != null && showDescendants) {
Node parent = get(parentId);
String treeNumber = parent.getTreeNumber();
list = dao.findAll(spec(null, treeNumber, userId, allNode, params),
sort);
} else {
list = dao.findAll(spec(parentId, null, userId, allNode, params),
sort);
}
return list;
}
public RowSide<Node> findSide(Integer parentId, Boolean showDescendants,
Integer userId, boolean allNode, Map<String, String[]> params,
Node bean, Integer position, Sort sort) {
if (position == null) {
return new RowSide<Node>();
}
Limitable limit = RowSide.limitable(position, sort);
List<Node> list;
if (showDescendants != null && showDescendants) {
String treeNumber = null;
if (parentId != null) {
Node parent = get(parentId);
treeNumber = parent.getTreeNumber();
}
list = dao.findAll(spec(null, treeNumber, userId, allNode, params),
limit);
} else {
if (parentId != null) {
list = dao.findAll(
spec(parentId, null, userId, allNode, params), limit);
} else {
list = Collections.emptyList();
}
}
return RowSide.create(list, bean);
}
private Specification<Node> spec(final Integer parentId,
final String treeNumber, final Integer userId,
final boolean allNode, Map<String, String[]> params) {
Collection<SearchFilter> filters = SearchFilter.parse(params).values();
final Specification<Node> fs = SearchFilter.spec(filters, Node.class);
Specification<Node> sp = new Specification<Node>() {
public Predicate toPredicate(Root<Node> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate pred = fs.toPredicate(root, query, cb);
if (parentId != null) {
pred = cb.and(pred, cb.equal(root.get("parent")
.<Integer> get("id"), parentId));
}
if (StringUtils.isNotBlank(treeNumber)) {
Path<String> tnPath = root.<String> get("treeNumber");
pred = cb.and(pred, cb.like(tnPath, treeNumber + "%"));
}
if (!allNode) {
Path<Integer> userPath = root.join("nodeRoleSites")
.join("role").join("users").<Integer> get("id");
pred = cb.and(pred, cb.equal(userPath, userId));
query.distinct(true);
}
return pred;
}
};
return sp;
}
public List<Node> findList(Integer[] siteId, Integer parentId,
String treeNumber, Boolean isRealNode, Boolean isHidden,
Limitable limitable) {
return dao.findList(siteId, parentId, treeNumber, isRealNode, isHidden,
limitable);
}
public Page<Node> findPage(Integer[] siteId, Integer parentId,
String treeNumber, Boolean isRealNode, Boolean isHidden,
Pageable pageable) {
return dao.findPage(siteId, parentId, treeNumber, isRealNode, isHidden,
pageable);
}
public List<Node> findByIds(Integer... ids) {
if (ArrayUtils.isEmpty(ids)) {
return Collections.emptyList();
}
return dao.findAll(Arrays.asList(ids));
}
public List<Node> findByIds(Integer[] ids, Integer selfId) {
List<Node> list = new ArrayList<Node>();
if (!ArrayUtils.isEmpty(ids)) {
Set<Integer> idSet = new HashSet<Integer>();
for (Integer id : ids) {
if (!idSet.contains(id) && !id.equals(selfId)) {
idSet.add(id);
list.add(get(id));
}
}
}
list.add(get(selfId));
return list;
}
public List<Node> findList(Integer siteId, Integer parentId) {
return findList(siteId, parentId, null, null);
}
public List<Node> findList(Integer siteId, Integer parentId,
Boolean isRealNode, Boolean isHidden) {
String treeNumber = null;
if (parentId != null) {
Node node = get(parentId);
if (node != null) {
treeNumber = node.getTreeNumber();
}
}
Sort sort = new Sort("treeNumber");
Limitable limitable = new LimitRequest(null, null, sort);
return dao.findList(new Integer[] { siteId }, null, treeNumber,
isRealNode, isHidden, limitable);
}
public List<Node> findChildren(Integer parentId) {
return findChildren(parentId, null, null, null, null);
}
public List<Node> findChildren(Integer parentId, Boolean isRealNode,
Boolean isHidden, Integer offset, Integer limit) {
if (parentId == null) {
return Collections.emptyList();
}
Sort sort = new Sort("treeNumber");
Limitable limitable = new LimitRequest(offset, limit, sort);
return dao.findList(null, parentId, null, isRealNode, isHidden,
limitable);
}
public Node findRoot(Integer siteId) {
List<Node> list = dao.findBySiteIdAndParentIdIsNull(siteId);
return !list.isEmpty() ? list.get(0) : null;
}
public Node findByNumber(Integer siteId, String number) {
List<Node> list = dao.findBySiteIdAndNumber(siteId, number);
return !list.isEmpty() ? list.get(0) : null;
}
public List<Node> findByNumber(String[] numbers) {
List<Node> list = dao.findByNumbers(numbers);
return list;
}
public List<Node> findByNumberLike(String[] numbers) {
List<Node> list = dao.findByNumbersLike(numbers);
return list;
}
public Node get(Integer id) {
return dao.findOne(id);
}
private NodeDao dao;
@Autowired
public void setDao(NodeDao dao) {
this.dao = dao;
}
}