Java tutorial
/* Copyright 2013 Mael Le Guvel This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See the COPYING file for more details. */ package fr.mael.microrss.dao.impl; import java.io.IOException; import java.util.List; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.queryParser.MultiFieldQueryParser; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.InvalidTokenOffsetsException; import org.apache.lucene.search.highlight.QueryScorer; import org.apache.lucene.search.highlight.SimpleHTMLFormatter; import org.apache.lucene.search.highlight.SimpleSpanFragmenter; import org.apache.lucene.util.Version; import org.hibernate.CacheMode; import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.FlushMode; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.criterion.Property; import org.hibernate.search.FullTextQuery; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.springframework.stereotype.Repository; import fr.mael.microrss.dao.UserArticleDao; import fr.mael.microrss.domain.Feed; import fr.mael.microrss.domain.User; import fr.mael.microrss.domain.UserArticle; import fr.mael.microrss.domain.UserLabel; @Repository public class UserArticleDaoImpl extends GenericDaoImpl<UserArticle> implements UserArticleDao { @Override public List<UserArticle> articlesForFeedAndUser(User user, Feed feed, int start, int nb) { StringBuffer query = new StringBuffer("select ua from UserArticle ua "); query.append("inner join fetch ua.article a "); query.append("inner join fetch a.feeds f "); query.append("inner join f.userFeeds uf "); query.append("left join fetch ua.userLabels "); query.append("where uf.user = :user "); query.append("and ua.user = :user "); query.append("and f = :feed "); Query q = getSession().createQuery(query.toString()); q.setEntity("user", user); q.setEntity("feed", feed); q.setFirstResult(start); q.setMaxResults(nb); return (List<UserArticle>) q.list(); } public List<UserArticle> search(String queryStr, User user, int start, int nb) throws ParseException, IOException, InvalidTokenOffsetsException { FullTextSession searchSession = Search.getFullTextSession(getSessionFactory().getCurrentSession()); QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_31, new String[] { "article.content", "article.title" }, new StandardAnalyzer(Version.LUCENE_31)); org.apache.lucene.search.Query query = parser.parse(queryStr); FullTextQuery hibQuery = searchSession.createFullTextQuery(query, UserArticle.class); Criteria fetchingStrategy = searchSession.createCriteria(UserArticle.class); fetchingStrategy.setFetchMode("article.feed", FetchMode.JOIN); fetchingStrategy.setFetchMode("userLabels", FetchMode.JOIN); fetchingStrategy.add(Property.forName("user").eq(user)); hibQuery.setCriteriaQuery(fetchingStrategy); hibQuery.setFirstResult(start); hibQuery.setMaxResults(nb); QueryScorer scorer = new QueryScorer(query); SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("[highlight]", "[/highlight]"); Highlighter highlighter = new Highlighter(formatter, scorer); highlighter.setTextFragmenter(new SimpleSpanFragmenter(scorer, 200)); List<UserArticle> userArticles = (List<UserArticle>) hibQuery.list(); for (UserArticle userArticle : userArticles) { String highlight = highlighter.getBestFragment(new StandardAnalyzer(Version.LUCENE_32), "content", userArticle.getArticle().getContent()); if (highlight != null) { highlight = highlight.replaceAll("\\<.*?>", "").replace("\n", " "); userArticle.getArticle().setHighlight(highlight); } } return userArticles; } @Override public void read(Integer userArticleId) { StringBuffer query = new StringBuffer("update UserArticle ua "); query.append("set read = :isRead "); query.append("where ua.id = :articleId "); Query q = getSession().createQuery(query.toString()); q.setBoolean("isRead", true); q.setInteger("articleId", userArticleId); q.executeUpdate(); } public void reindex() { FullTextSession searchSession = null; searchSession = Search.getFullTextSession(getSessionFactory().getCurrentSession()); searchSession.setFlushMode(FlushMode.MANUAL); searchSession.setCacheMode(CacheMode.IGNORE); searchSession.purgeAll(UserArticle.class); manageResults(UserArticle.class, searchSession); } private void manageResults(Class clazz, FullTextSession searchSession) { ScrollableResults results = searchSession.createCriteria(clazz).setFetchMode("article", FetchMode.JOIN) .setFetchSize(100).scroll(ScrollMode.FORWARD_ONLY); int index = 0; while (results.next()) { index++; searchSession.index(results.get(0)); if (index % 100 == 0) { searchSession.flushToIndexes(); searchSession.clear(); } } searchSession.flushToIndexes(); searchSession.clear(); } @Override public void read(Integer[] userArticleIds) { StringBuffer query = new StringBuffer("update UserArticle ua "); query.append("set read = :isRead "); query.append("where ua.id in (:articleIds) "); Query q = getSession().createQuery(query.toString()); q.setBoolean("isRead", true); q.setParameterList("articleIds", userArticleIds); q.executeUpdate(); } @Override public List<UserArticle> getForLabel(UserLabel label, int start, int nb) { StringBuffer query = new StringBuffer("select ua from UserArticle ua "); query.append("left join fetch ua.userLabels "); query.append("inner join ua.userLabels ul "); query.append("where ul = :label "); Query q = getSession().createQuery(query.toString()); q.setEntity("label", label); q.setFirstResult(start); q.setMaxResults(nb); return (List<UserArticle>) q.list(); } @Override public void star(Integer userArticleId, boolean star) { StringBuffer query = new StringBuffer("update UserArticle ua "); query.append("set starred = :starred "); query.append("where ua.id = :articleId "); Query q = getSession().createQuery(query.toString()); q.setBoolean("starred", star); q.setInteger("articleId", userArticleId); q.executeUpdate(); } @Override public List<UserArticle> getStarred(User user, int start, int nb) { StringBuffer query = new StringBuffer("from UserArticle ua "); query.append("left join fetch ua.userLabels "); query.append("where ua.starred = :starred "); query.append("and ua.user = :user "); Query q = getSession().createQuery(query.toString()); q.setBoolean("starred", true); q.setEntity("user", user); q.setFirstResult(start); q.setMaxResults(nb); return (List<UserArticle>) q.list(); } @Override public Long unreadStarred(User user) { StringBuffer query = new StringBuffer("select count(ua) from UserArticle ua "); query.append("where ua.user = :user "); query.append("and ua.read = :read "); query.append("and ua.starred = :starred"); Query q = getSession().createQuery(query.toString()); q.setEntity("user", user); q.setBoolean("read", false); q.setBoolean("starred", true); return (Long) q.uniqueResult(); } @Override public Long labelUnread(User user, UserLabel label) { StringBuffer query = new StringBuffer("select count(ua) from UserArticle ua "); query.append("inner join ua.userLabels ul "); query.append("where ua.user = :user "); query.append("and ua.read = :read "); query.append("and ul = :label "); Query q = getSession().createQuery(query.toString()); q.setEntity("user", user); q.setBoolean("read", false); q.setEntity("label", label); return (Long) q.uniqueResult(); } }