/*** ** @(#) TradeCard.com 1.0 ** ** Copyright (c) 2010 TradeCard, Inc. All Rights Reserved. ** ** ** THIS COMPUTER SOFTWARE IS THE PROPERTY OF TradeCard, Inc. ** ** Permission is granted to use this software as specified by the TradeCard ** COMMERCIAL LICENSE AGREEMENT. You may use this software only for ** commercial purposes, as specified in the details of the license. ** TRADECARD SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY ** THE LICENSEE AS A RESULT OF USING OR MODIFYING THIS SOFTWARE IN ANY WAY. ** ** YOU MAY NOT DISTRIBUTE ANY SOURCE CODE OR OBJECT CODE FROM THE TradeCard.com ** TOOLKIT AT ANY TIME. VIOLATORS WILL BE PROSECUTED TO THE FULLEST EXTENT ** OF UNITED STATES LAW. ** ** @version 1.0 ** @author Copyright (c) 2010 TradeCard, Inc. All Rights Reserved. ** **/ package com.partydj.search; import java.util.*; import java.util.regex.*; import org.apache.commons.codec.language.*; import org.apache.lucene.analysis.standard.*; import org.apache.lucene.document.*; import org.apache.lucene.index.*; import org.apache.lucene.queryParser.*; import org.apache.lucene.search.*; import org.apache.lucene.store.*; import org.apache.lucene.util.*; import org.cmc.music.metadata.*; import com.partydj.player.*; import com.partydj.util.*; /** * **/ public class LuceneSearchProvider implements SearchProvider { public static final DoubleMetaphone INDEX_ENCODER = new DoubleMetaphone(); Map<Document, MediaFile> indexToMediaFile = new HashMap(); private static final Directory index = new RAMDirectory(); private static final StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT); private static final IndexWriter indexWriter = makeIndexWriter(); private static IndexWriter makeIndexWriter() { try { return new IndexWriter(index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED); } catch (Exception e) { e.printStackTrace(); return null; } } @Override public void addToSearchIndex(MediaFile file) { IMusicMetadata metadata = file.getMetadata(); try { Document doc = new Document(); if (metadata.getArtist() != null) { doc.add(new Field(MediaFile.ARTIST, INDEX_ENCODER.encode(metadata.getArtist()), Field.Store.YES, Field.Index.ANALYZED)); } if (metadata.getAlbum() != null) { doc.add(new Field(MediaFile.ALBUM, INDEX_ENCODER.encode(metadata.getAlbum()), Field.Store.YES, Field.Index.ANALYZED)); } doc.add(new Field(MediaFile.TITLE, INDEX_ENCODER.encode(metadata.getSongTitle()), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field(ANY, INDEX_ENCODER.encode(file.getSimpleName()), Field.Store.YES, Field.Index.ANALYZED)); indexWriter.addDocument(doc); indexToMediaFile.put(doc, file); } catch (Exception e) { e.printStackTrace(); } } //for now only use the first value @Override public Collection<MediaFile> find(Map<String, Collection<String>> queryParameters) { StringBuilder queryString = new StringBuilder(); if (queryString == null || queryString.length() == 0) { return Collections.emptyList(); } else { String any = getFirst(queryParameters, ANY); if (any != null) { queryString.append(INDEX_ENCODER.encode(any)); } else { //$MR todo } List<MediaFile> found = new ArrayList(); try { Query query = new QueryParser(Version.LUCENE_CURRENT, ANY, analyzer).parse(queryString.toString()); Integer hitsPerPage = getFirstInteger(queryParameters, MAX_RESULTS); if (hitsPerPage == null) { hitsPerPage = DEFAULT_MAX_RESULTS; } IndexSearcher searcher = new IndexSearcher(index, true); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); //$MR jaro-winlker scorer searcher.search(query, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs; for (ScoreDoc hit : hits) { Document d = searcher.doc(hit.doc); found.add(indexToMediaFile.get(d)); } } catch (Exception e) { e.printStackTrace(); } return found; } } private static Integer getFirstInteger(Map<String, Collection<String>> map, String key) { String string = getFirst(map, key); if (string != null) { try { return Integer.valueOf(string); } catch (Exception e) { } } return null; } private static String getFirst(Map<String, Collection<String>> map, String key) { Collection<String> c = map.get(key); if (c != null && c.size() > 0) { return c.iterator().next(); } return null; } }