/* 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.
*/
package org.riotfamily.core.dao.hibernate;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.riotfamily.common.hibernate.HibernateUtils;
import org.riotfamily.core.dao.ListParams;
import org.riotfamily.core.dao.Order;
import org.riotfamily.core.dao.Searchable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
* RiotDao implementation based on Hibernate.
*/
public abstract class AbstractHqlDao extends AbstractHibernateRiotDao
implements Searchable {
private Logger log = LoggerFactory.getLogger(AbstractHqlDao.class);
private String[] searchableProperties;
public AbstractHqlDao(SessionFactory sessionFactory) {
super(sessionFactory);
}
protected boolean isPolymorph() {
return true;
}
protected String getSelect() {
return "this";
}
protected String getFrom(ListParams params) {
StringBuilder from = new StringBuilder();
from.append(getEntityClass().getName());
from.append(" as this");
return from.toString();
}
public void setSearch(String search) {
searchableProperties = StringUtils.tokenizeToStringArray(search, " ,\t\r\n");
}
public String[] getSearchableProperties() {
return searchableProperties;
}
protected String getWhere() {
return null;
}
protected boolean isPrefixSearch() {
return true;
}
protected boolean isSuffixSearch() {
return true;
}
/**
* Returns a list of items.
*/
@Override
protected List<?> listInternal(Object parent, ListParams params) {
Query query = getSession().createQuery(buildHql(parent, params));
setQueryParameters(query, parent, params);
if (params.getPageSize() > 0) {
query.setFirstResult(params.getOffset());
query.setMaxResults(params.getPageSize());
}
return query.list();
}
/**
* Returns the total number of items.
*/
@Override
public int getListSize(Object parent, ListParams params) {
Query query = getSession().createQuery(buildCountHql(parent, params));
setQueryParameters(query, parent, params);
Number size = (Number) query.uniqueResult();
if (size == null) {
return 0;
}
return size.intValue();
}
protected void setQueryParameters(Query query, Object parent,
ListParams params) {
if (params.getFilter() != null) {
setFilterParameters(query, params);
}
if (params.getSearch() != null) {
String search = params.getSearch().toLowerCase();
if (isPrefixSearch()) {
search += '%';
}
if (isSuffixSearch()) {
search = '%' + search;
}
if (!isPrefixSearch() && !isSuffixSearch()) {
search = search.replace('*', '%');
}
query.setParameter("search", search);
}
}
/**
* Builds a HQL query string to retrieve the total number of items.
*/
protected String buildCountHql(Object parent, ListParams params) {
StringBuilder hql = new StringBuilder();
hql.append("select count(*)");
appendFromClause(hql, params);
HqlUtils.appendHql(hql, "where", getWhereClause(parent, params));
log.debug(hql.toString());
return hql.toString();
}
/**
* Builds a HQL query string to retrieve a list of items.
*/
protected String buildHql(Object parent, ListParams params) {
StringBuilder hql = new StringBuilder();
hql.append("select ");
hql.append(getSelect());
appendFromClause(hql, params);
HqlUtils.appendHql(hql, "where", getWhereClause(parent, params));
HqlUtils.appendHql(hql, "order by", getOrderBy(params));
log.debug(hql.toString());
return hql.toString();
}
protected void appendFromClause(StringBuilder hql, ListParams params) {
hql.append(" from ");
hql.append(getFrom(params));
}
protected String getWhereClause(Object parent, ListParams params) {
StringBuilder sb = new StringBuilder();
HqlUtils.appendHql(sb, null, getWhere());
if (params.getFilter() != null) {
HqlUtils.appendHql(sb, "and", getFilterWhereClause(params));
}
if (params.getSearch() != null) {
HqlUtils.appendHql(sb, "and", getSearchWhereClause(params));
}
if (!isPolymorph()) {
HqlUtils.appendHql(sb, "and", "(this.class = ")
.append(getEntityClass().getName()).append(')');
}
return sb.toString();
}
protected String getFilterWhereClause(ListParams params) {
return HqlUtils.getExampleWhereClause(getEntityClass(),
params.getFilter(), "this", params.getFilteredProperties());
}
@SuppressWarnings("unchecked")
protected void setFilterParameters(Query query, ListParams params) {
if (params.getFilter() instanceof Map) {
Map<String, ?> filterMap = (Map<String, ?>) params.getFilter();
for (Map.Entry<String, ?> entry: filterMap.entrySet()) {
String name = entry.getKey();
HibernateUtils.setParameter(query, name.replaceAll("\\.", "_dot_"), entry.getValue());
}
}
else {
query.setProperties(params.getFilter());
}
HqlUtils.setCollectionValueParams(query,
params.getFilteredProperties(), getEntityClass(),
params.getFilter());
}
protected String getSearchWhereClause(ListParams params) {
return HqlUtils.getSearchWhereClause(getEntityClass().getName(), "this", "search", getSearchableProperties());
}
protected String getOrderBy(ListParams params) {
StringBuilder sb = new StringBuilder();
if (params.hasOrder()) {
Iterator<Order> it = params.getOrder().iterator();
while (it.hasNext()) {
Order order = it.next();
if (!order.isCaseSensitive()) {
sb.append(" lower(");
}
sb.append(" this.");
sb.append(order.getProperty());
if (!order.isCaseSensitive()) {
sb.append(" ) ");
}
sb.append(' ');
sb.append(order.isAscending() ? "asc" : "desc");
if (it.hasNext()) {
sb.append(',');
}
}
}
return sb.toString();
}
}