package com.manning.hsia.dvdstore.action.jpa; import java.util.ArrayList; import java.util.List; import javax.persistence.NoResultException; import javax.persistence.Query; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Explanation; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.Session; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextQuery; import org.hibernate.transform.AliasToBeanResultTransformer; import com.manning.hsia.dvdstore.action.DisplayAction; import com.manning.hsia.dvdstore.action.ItemView; import com.manning.hsia.dvdstore.action.OrderBy; import com.manning.hsia.dvdstore.action.ResultHolder; import com.manning.hsia.dvdstore.model.Item; import com.manning.hsia.dvdstore.util.EntityManagerHolder; public class DisplayActionImpl implements DisplayAction { /** * Example 6.9 */ public List<String> displayAllByMatchingTitle(String words) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); javax.persistence.Query query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Item> items = query.getResultList(); List<String> results = new ArrayList<String>(); for (Item item : items) { StringBuilder itemInString = new StringBuilder("Item ") .append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()); results.add( itemInString.toString() ); } return results; } /** * Returns the matching results. Each result is represented by a string representation * * @param words matching words * @param pageNumber number of the displayed page starting from 1 * @param window number of elements per page * * @return list of matching results represented as String * * Example 6.14 */ public List<String> displayAllByMatchingTitle(String words, int pageNumber, int window) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); javax.persistence.Query query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Item> items = query .setFirstResult( (pageNumber - 1) * window ) //set pagination according to window .setMaxResults( window ) .getResultList(); List<String> results = new ArrayList<String>(); for (Item item : items) { StringBuilder itemInString = new StringBuilder("Item ") .append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()); results.add( itemInString.toString() ); } return results; } /** * Example 6.13 */ public String displayIMFeelingLuckyByMatchingTitle(String words) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); javax.persistence.Query query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); Query hSearchQuery = query .setFirstResult(0).setMaxResults(1); Item item; try { item = (Item) hSearchQuery.getSingleResult(); //return one element } catch (NoResultException e) { //guard against no element found item = null; } StringBuilder itemInString = new StringBuilder("Item "); if (item == null) { itemInString.append("not found"); } else { itemInString.append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()); } return itemInString.toString(); } /** * Example 6.15 */ public int displayResultSizeByMatchingTitle(String words) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); return query.getResultSize(); //number of matching results (cheap) } /** * Example 6.23 */ public Explanation explainFirstMatchingItem(String words) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") Object[] result = (Object[]) query .setProjection( FullTextQuery.DOCUMENT_ID, //retrieve the doucment id FullTextQuery.THIS) .setMaxResults(1) .getSingleResult(); return query.explain( (Integer) result[0] ); //explain a given document } private org.apache.lucene.search.Query buildLuceneQuery(String words, Class<?> searchedEntity) { Analyzer analyzer; if (searchedEntity == null) { //get the most appropriate analyzer analyzer = new StandardAnalyzer(); } else { analyzer = EntityManagerHolder.getFullTextEntityManager().getSearchFactory().getAnalyzer(searchedEntity); } QueryParser parser = new QueryParser( "title", analyzer ); org.apache.lucene.search.Query luceneQuery = null; try { luceneQuery = parser.parse(words); } catch (org.apache.lucene.queryParser.ParseException e) { throw new IllegalArgumentException("Unable to parse search entry into a Lucene query", e); } return luceneQuery; } /** * Example 6.20 */ public List<String> displayAllByMatchingTitleOrderedBy(String words, OrderBy orderBy) { FullTextEntityManager ftEntityManager = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEntityManager.createFullTextQuery(luceneQuery, Item.class); Sort sort = null; switch (orderBy) { case EAN: { //sort by ean SortField sortField = new SortField("ean", SortField.STRING); //build a SortField sort = new Sort(sortField); //wrap it in a Sort break; } case TITLE_THEN_EAN: { //sort by title and for equals titles by ean SortField[] sortFields = new SortField[2]; //multiple sort fields are possible sortFields[0] = new SortField("title_sort", SortField.STRING); sortFields[1] = new SortField("ean", SortField.STRING); sort = new Sort(sortFields); break; } case TITLE_THEN_SCORE: { //sort by title and for equals titles by ean SortField[] sortFields = new SortField[2]; sortFields[0] = new SortField("title_sort", SortField.STRING); //use the special SortField sortFields[1] = SortField.FIELD_SCORE; //sort by score after title sort = new Sort(sortFields); break; } default: assert sort == null: "Unknown OrderBy." + orderBy; } query.setSort( sort ); //assign Sort to the query @SuppressWarnings("unchecked") List<Item> items = query.getResultList(); List<String> results = new ArrayList<String>(); for (Item item : items) { StringBuilder itemInString = new StringBuilder("Item ") .append(item.getTitle()) .append(" (").append(item.getEan() ).append(")"); results.add( itemInString.toString() ); } return results; } public List<String> displayAllByMatchingTitleUsingCache(String words) { //cannot be implemented with JPA return null; } public List<String> displayMediumResultsByMatchingTitle(String words, int n) { //cannot be implemented with JPA return null; } /** * Example 6/22 */ public List<String> displayItemAndDistributorByMatchingTitle(String words) { FullTextEntityManager ftEm = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEm.createFullTextQuery(luceneQuery, Item.class); final Session session = (Session) ftEm.getDelegate(); Criteria fetchingStrategy = session.createCriteria(Item.class) //create criteria on targeted entit .setFetchMode("distributor", FetchMode.JOIN); //set fetching profil query.setCriteriaQuery(fetchingStrategy); @SuppressWarnings("unchecked") List<Item> items = query.getResultList(); List<String> results = new ArrayList<String>(); for (Item item : items) { StringBuilder itemInString = new StringBuilder("Item ") .append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()) .append(" - ").append(item.getDistributor().getName()); //use pre loaded association results.add( itemInString.toString() ); } return results; } /** * Example 6.17 */ public List<ItemView> displayProjectionAndMetadataByMatchingTitle(String words) { FullTextEntityManager ftEm = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEm.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Object[]> results = query .setProjection( "ean", "title", FullTextQuery.SCORE) //project the document score .getResultList(); List<ItemView> endResults = new ArrayList<ItemView>(results.size()); for (Object[] line : results) { ItemView itemView = new ItemView( (String) line[0], (String) line[1], (Float) line[2] ); //retrieve the document score endResults.add( itemView ); } return endResults; } /** * Example 6.16 */ public List<ItemView> displayProjectionByMatchingTitle(String words) { FullTextEntityManager ftEm = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEm.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Object[]> results = query .setProjection("ean", "title") //set the projected properties .getResultList(); List<ItemView> endResults = new ArrayList<ItemView>(results.size()); for (Object[] line : results) { endResults.add( new ItemView( (String) line[0], //build object from projection array (String) line[1]) ); } return endResults; } /** * Example 6.19 */ public List<ItemView> displayProjectionUsingResultTransformerByMatchingTitle(String words) { FullTextEntityManager ftEm = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEm.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<ItemView> results = query .setProjection("ean", "title") .setResultTransformer( new AliasToBeanResultTransformer(ItemView.class) //attach the result transformer ) .getResultList(); return results; } /** * Example 6.15 */ public ResultHolder displayResultsAndTotalByMatchingTitle(String words, int pageNumber, int window) { FullTextEntityManager ftEm = EntityManagerHolder.getFullTextEntityManager(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftEm.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<String> results = query .setFirstResult( (pageNumber - 1) * window ) .setMaxResults(window) .getResultList(); //return matching results int resultSize = query.getResultSize(); //return total number of results ResultHolder holder = new ResultHolder(results, resultSize); return holder; } }