package com.manning.hsia.dvdstore.action; import java.util.ArrayList; import java.util.Iterator; import java.util.List; 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.ScrollableResults; import org.hibernate.search.FullTextQuery; import org.hibernate.search.FullTextSession; import org.hibernate.transform.AliasToBeanResultTransformer; import com.manning.hsia.dvdstore.model.Item; import com.manning.hsia.dvdstore.util.SessionHolder; public class DisplayActionImpl implements DisplayAction { /** * Example 6.9 */ public List<String> displayAllByMatchingTitle(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); org.hibernate.Query query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Item> items = query.list(); //return a list of items 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) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); org.hibernate.Query query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Item> items = query .setFirstResult( (pageNumber - 1) * window ) //set first result from the page .setMaxResults( window ) //set number of results .list(); 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) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); org.hibernate.Query query = ftSession.createFullTextQuery(luceneQuery, Item.class); Item item = (Item) query .setFirstResult(0).setMaxResults(1) //use pagination to return one result .uniqueResult(); //return one element 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.10 */ public List<String> displayAllByMatchingTitleUsingCache(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); org.hibernate.Query query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") Iterator<Item> items = query.iterate(); //retrieve an iterator on items List<String> results = new ArrayList<String>(); while ( items.hasNext() ) { Item item = items.next(); //load object from the persistence context StringBuilder itemInString = new StringBuilder("Item ") .append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()); results.add(itemInString.toString()); } return results; } /** * Display results starting from the middle of the list up to n elements * * Example 6.11 */ public List<String> displayMediumResultsByMatchingTitle(String words, int n) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); query.setFetchSize(n); //define fetch size ScrollableResults items = query.scroll(); //retrieve a ScrollableResults List<String> results = new ArrayList<String>(); try { items.beforeFirst(); //go to the first position //get the jump to the position before the medium element int mediumIndexJump = query.getResultSize() / 2; items.scroll(mediumIndexJump); //jump to a specific position int index = 0; while(index < n) { if ( items.next() ) { //load the next element Item item = (Item) items.get()[0]; //read the object if ( item != null ) { StringBuilder itemInString = new StringBuilder("Item ") .append("(").append(item.getEan()).append(")") .append(" ").append(item.getTitle()); results.add(itemInString.toString()); index++; } else { //mismatch between the index and the database: ignore null entries } } else { break; } } } finally { items.close(); //close resources } return results; } /** * Example 6.15 */ public int displayResultSizeByMatchingTitle(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); return query.getResultSize(); //nbumber of matching results (cheap) } /** * Example 6.15 */ public ResultHolder displayResultsAndTotalByMatchingTitle(String words, int pageNumber, int window) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<String> results = query .setFirstResult( (pageNumber - 1) * window ) .setMaxResults(window) .list(); //return matching results int resultSize = query.getResultSize(); //return total number of results ResultHolder holder = new ResultHolder(results, resultSize); return holder; } /** * Example 6.16 */ public List<ItemView> displayProjectionByMatchingTitle(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Object[]> results = query .setProjection("ean", "title") //set the projected properties .list(); 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.17 */ public List<ItemView> displayProjectionAndMetadataByMatchingTitle(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<Object[]> results = query .setProjection( "ean", "title", FullTextQuery.SCORE) //project the document score .list(); 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.19 */ public List<ItemView> displayProjectionUsingResultTransformerByMatchingTitle(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") List<ItemView> results = query .setProjection("ean", "title") .setResultTransformer( new AliasToBeanResultTransformer(ItemView.class) //attach the result transformer ) .list(); return results; } /** * Example 6.20 */ public List<String> displayAllByMatchingTitleOrderedBy(String words, OrderBy orderBy) { org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextSession ftSession = SessionHolder.getFullTextSession(); FullTextQuery query = ftSession.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.list(); 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> displayItemAndDistributorByMatchingTitle(String words) { org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextSession ftSession = SessionHolder.getFullTextSession(); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); Criteria fetchingStrategy = ftSession.createCriteria(Item.class) //create criteria on targeted entit .setFetchMode("distributor", FetchMode.JOIN); //set fetching profil query.setCriteriaQuery(fetchingStrategy); @SuppressWarnings("unchecked") List<Item> items = query.list(); 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.23 */ public Explanation explainFirstMatchingItem(String words) { FullTextSession ftSession = SessionHolder.getFullTextSession(); org.apache.lucene.search.Query luceneQuery = buildLuceneQuery(words, Item.class); FullTextQuery query = ftSession.createFullTextQuery(luceneQuery, Item.class); @SuppressWarnings("unchecked") Object[] result = (Object[]) query .setProjection( FullTextQuery.DOCUMENT_ID, //retrieve the docuemnt id FullTextQuery.THIS) .setMaxResults(1) .uniqueResult(); 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 = SessionHolder.getFullTextSession().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; } }