/*
* Copyright 2008 Jeff Dwyer
*
* 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 com.apress.progwt.server.dao.hibernate;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.apress.progwt.client.domain.Application;
import com.apress.progwt.client.domain.ForumPost;
import com.apress.progwt.client.domain.Loadable;
import com.apress.progwt.client.domain.ProcessType;
import com.apress.progwt.client.domain.RatingType;
import com.apress.progwt.client.domain.School;
import com.apress.progwt.client.domain.SchoolForumPost;
import com.apress.progwt.client.domain.User;
import com.apress.progwt.client.domain.UserForumPost;
import com.apress.progwt.client.domain.dto.PostsList;
import com.apress.progwt.server.dao.SchoolDAO;
public class SchoolDAOHibernateImpl extends HibernateDaoSupport implements
SchoolDAO {
private int autoCompleteMax = 7;
private static final Logger log = Logger
.getLogger(SchoolDAOHibernateImpl.class);
public Loadable get(Class<? extends Loadable> loadable, Long id) {
return (Loadable) getHibernateTemplate().get(loadable, id);
}
public List<School> getAllSchools(int start, int max) {
DetachedCriteria crit = DetachedCriteria.forClass(School.class)
.addOrder(Order.desc("popularityCounter"));
// .add(
// Expression.and(Expression.gt("id", 890l),
// Expression.eq("latitude", -1d)));
List<School> list = getHibernateTemplate().findByCriteria(crit,
start, max);
return list;
}
public List<ProcessType> getDefaultProcessTypes() {
DetachedCriteria crit = DetachedCriteria.forClass(
ProcessType.class).add(
Expression.eq("useByDefault", true)).addOrder(
Order.asc("id"));
return getHibernateTemplate().findByCriteria(crit);
}
public List<RatingType> getDefaultRatingTypes() {
DetachedCriteria crit = DetachedCriteria.forClass(
RatingType.class)
.add(Expression.eq("useByDefault", true)).addOrder(
Order.asc("id"));
return getHibernateTemplate().findByCriteria(crit);
}
public ProcessType getProcessForName(String string) {
DetachedCriteria crit = DetachedCriteria.forClass(
ProcessType.class).add(Expression.eq("name", string));
return (ProcessType) DataAccessUtils
.uniqueResult(getHibernateTemplate().findByCriteria(crit));
}
public School getSchoolFromName(String name) {
return (School) DataAccessUtils
.uniqueResult(getHibernateTemplate().find(
"from School where name=?", name));
}
public List<School> getSchoolsMatching(String match) {
return getSchoolsMatching(match, 0, autoCompleteMax,
MatchMode.ANYWHERE);
}
/**
* use start matchmode
*/
public List<School> getSchoolsMatching(String match, int start,
int max) {
return getSchoolsMatching(match, start, max, MatchMode.START);
}
public List<School> getSchoolsMatching(String match, int start,
int max, MatchMode matchMode) {
DetachedCriteria crit = DetachedCriteria.forClass(School.class)
.add(Expression.ilike("name", match, matchMode))
.addOrder(Order.asc("name"));
List<School> list = getHibernateTemplate().findByCriteria(crit,
start, max);
return list;
}
public List<ProcessType> matchProcessType(String queryString) {
DetachedCriteria crit = DetachedCriteria.forClass(
ProcessType.class)
.add(
Expression.ilike("name", queryString,
MatchMode.ANYWHERE)).addOrder(
Order.asc("name"));
List<ProcessType> list = getHibernateTemplate().findByCriteria(
crit, 0, autoCompleteMax);
return list;
}
public Loadable save(Loadable loadable) {
getHibernateTemplate().saveOrUpdate(loadable);
return loadable;
}
public void delete(Loadable loadable) {
getHibernateTemplate().delete(loadable);
getHibernateTemplate().flush();
}
/**
* Change the number of autocomplete matches that are returned.
*
* @param autoCompleteMax
*/
public void setAutoCompleteMax(int autoCompleteMax) {
this.autoCompleteMax = autoCompleteMax;
}
public int getAutoCompleteMax() {
return autoCompleteMax;
}
/**
* get the total number of rows without actually returning all rows
* NOTE: important to set the start row here, otherwise when we start
* paging, this criteria will be affected and we won't get the first
* row.
*
* @param criteria
* @return
*/
private int getRowCount(DetachedCriteria criteria) {
criteria.setProjection(Projections.rowCount());
return ((Integer) getHibernateTemplate().findByCriteria(criteria,
0, 1).get(0)).intValue();
}
/**
*
* Posts that are threads will have their threadPost field == null.
*
* Could try to optimize by getting close to: SELECT f.id,
* f.thread_id, count(s.id) FROM `forumposts` f left JOIN forumposts s
* on f.id = s.thread_id WHERE f.thread_id IS NULL group by f.id
*
* @param topicName
*
*/
public PostsList getThreads(Class<? extends ForumPost> forumClass,
String topicName, long topicID, int start, int max) {
System.out.println("start " + start + " max " + max);
DetachedCriteria crit = DetachedCriteria.forClass(forumClass,
"fp").add(
Expression.and(Expression.eq(topicName, topicID),
Expression.isNull("threadPost"))).addOrder(
Order.desc("date"));
// alternative
// String query = "select post, count(rp) from " + forumClass
// + " post left join post.replies as rp where post."
// + topicName
// + " = ? and post.threadPost is null group by post."
// + topicName + " order by post.date desc ";
// List<Object[]> res = finder(query, topicID);
// List<ForumPost> posts = new ArrayList<ForumPost>(res.size());
// for (Object[] objects : res) {
// ForumPost fp = (ForumPost) objects[0];
// long count = (Long) objects[1];
// fp.setReplyCount((int) count);
// posts.add(fp);
// }
List<ForumPost> posts = getHibernateTemplate().findByCriteria(
crit, start, max);
// set the reply count so we can have this information w/o
// loading
// the actual set.
for (ForumPost fp : posts) {
fp.setReplyCount(fp.getReplies().size());
}
PostsList rtn = new PostsList(posts, getRowCount(crit));
return rtn;
}
private List finder(String hql, Object... args) {
return getHibernateTemplate().find(hql, args);
}
public PostsList getPostsForThread(ForumPost post, int start, int max) {
DetachedCriteria crit = DetachedCriteria
.forClass(ForumPost.class).add(
Expression.or(Expression.eq("threadPost.id", post
.getId()), Expression.eq("id", post
.getId()))).addOrder(Order.asc("date"));
List<ForumPost> posts = getHibernateTemplate().findByCriteria(
crit, start, max);
PostsList rtn = new PostsList(posts, getRowCount(crit));
return rtn;
}
public PostsList getSchoolThreads(long schoolID, int start, int max) {
return getThreads(SchoolForumPost.class, "school.id", schoolID,
start, max);
}
public PostsList getUserThreads(long userID, int start, int max) {
return getThreads(UserForumPost.class, "user.id", userID, start,
max);
}
public PostsList getRecentForumPosts(int start, int max) {
DetachedCriteria crit = DetachedCriteria.forClass(
ForumPost.class, "fp").add(
Expression.isNull("threadPost")).addOrder(
Order.desc("date"));
List<ForumPost> posts = getHibernateTemplate().findByCriteria(
crit, start, max);
PostsList rtn = new PostsList(posts, getRowCount(crit));
return rtn;
}
/**
* Batch Update in HQL
* http://www.hibernate.org/hib_docs/reference/en/html/batch.html#batch-direct
*/
public void incrementSchoolPopularity(final School school) {
getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String hql = "update School set popularityCounter = popularityCounter + 1 where id = :id";
int updated = session.createQuery(hql).setLong("id",
school.getId()).executeUpdate();
return updated;
}
});
}
public List<User> getUsersInterestedIn(School school) {
return getUsersInterestedIn(school, 10);
}
public List<User> getUsersInterestedIn(School school, int max) {
DetachedCriteria crit = DetachedCriteria.forClass(
Application.class, "app").add(
Expression.eq("school", school));
List<Application> applications = getHibernateTemplate()
.findByCriteria(crit, 0, max);
List<User> users = new ArrayList<User>(applications.size());
for (Application app : applications) {
users.add(app.getUser());
}
return users;
}
}