This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit 81b2cdd4f6adee991d74614788d8c38b28167587 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Dec 30 17:22:46 2014 +0100 add an indexation service for question : base on title, themes and summary --- .../coselmar/services/CoselmarServicesContext.java | 3 + .../services/CoselmarSimpleServiceSupport.java | 5 + .../services/DefaultCoselmarServicesContext.java | 11 + .../indexation/DocumentsIndexationService.java | 57 ++--- .../coselmar/services/indexation/LuceneUtils.java | 51 ++++ .../indexation/QuestionsIndexationService.java | 161 ++++++++++++ .../indexation/DocumentsIndexationServiceTest.java | 8 +- .../indexation/QuestionsIndexationServiceTest.java | 271 +++++++++++++++++++++ 8 files changed, 520 insertions(+), 47 deletions(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java index 43bc0a9..f242785 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java @@ -30,6 +30,7 @@ import java.util.Locale; import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; import fr.ifremer.coselmar.persistence.CoselmarTopiaApplicationContext; import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import fr.ifremer.coselmar.services.indexation.LuceneUtils; /** * Created by martel on 30/10/14. @@ -44,6 +45,8 @@ public interface CoselmarServicesContext { CoselmarServicesConfig getCoselmarServicesConfig(); + LuceneUtils getLuceneUtils(); + <E extends CoselmarService> E newService(Class<E> serviceClass); Locale getLocale(); diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarSimpleServiceSupport.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarSimpleServiceSupport.java index caca46a..2637293 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarSimpleServiceSupport.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarSimpleServiceSupport.java @@ -27,6 +27,7 @@ package fr.ifremer.coselmar.services; import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; import fr.ifremer.coselmar.persistence.entity.CoselmarUserTopiaDao; import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import fr.ifremer.coselmar.services.indexation.LuceneUtils; /** * @author ymartel <martel@codelutin.com> @@ -52,6 +53,10 @@ public class CoselmarSimpleServiceSupport implements CoselmarService { return getPersistenceContext().getCoselmarUserDao(); } + protected LuceneUtils getLuceneUtils() { + return servicesContext.getLuceneUtils(); + } + public void commit() { getPersistenceContext().commit(); } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java index 060e5b1..5f81b74 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java @@ -35,6 +35,7 @@ import java.util.Locale; import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; import fr.ifremer.coselmar.persistence.CoselmarTopiaApplicationContext; import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import fr.ifremer.coselmar.services.indexation.LuceneUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -54,6 +55,8 @@ public class DefaultCoselmarServicesContext implements CoselmarServicesContext { protected Locale locale; + protected LuceneUtils luceneUtils; + private CoselmarTopiaApplicationContext topiaApplicationContext; public void setCoselmarServicesConfig(CoselmarServicesConfig servicesConfig) { @@ -94,6 +97,14 @@ public class DefaultCoselmarServicesContext implements CoselmarServicesContext { } @Override + public LuceneUtils getLuceneUtils() { + if (this.luceneUtils == null) { + this.luceneUtils = new LuceneUtils(this.servicesConfig); + } + return this.luceneUtils; + } + + @Override public <E extends CoselmarService> E newService(Class<E> serviceClass) { E service; diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationService.java index 08a7c51..0c85c5b 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationService.java @@ -1,6 +1,5 @@ package fr.ifremer.coselmar.services.indexation; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -8,15 +7,11 @@ import java.util.Set; import fr.ifremer.coselmar.beans.DocumentBean; import fr.ifremer.coselmar.services.CoselmarSimpleServiceSupport; -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.core.SimpleAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.search.BooleanClause; @@ -25,9 +20,6 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.NIOFSDirectory; -import org.apache.lucene.util.Version; /** * This Services provides operation about {@link fr.ifremer.coselmar.persistence.entity.Document} @@ -45,10 +37,6 @@ import org.apache.lucene.util.Version; */ public class DocumentsIndexationService extends CoselmarSimpleServiceSupport { - public static Analyzer analyzer; - public static final IndexWriterConfig indexationConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, getAnalyzer()); - public static IndexWriter indexWriter; - protected static final String DOCUMENT_ID_INDEX_PROPERTY = "documentId"; protected static final String DOCUMENT_NAME_INDEX_PROPERTY = "documentName"; protected static final String DOCUMENT_AUTHORS_INDEX_PROPERTY = "documentAuthors"; @@ -71,14 +59,13 @@ public class DocumentsIndexationService extends CoselmarSimpleServiceSupport { doc.add(new Field(DOCUMENT_KEYWORD_INDEX_PROPERTY, keyword, TextField.TYPE_STORED)); } - - getIndexWriter().addDocument(doc); - getIndexWriter().commit(); + getLuceneUtils().getIndexWriter().addDocument(doc); + getLuceneUtils().getIndexWriter().commit(); } public List<String> searchDocuments(String text) throws IOException, ParseException { - DirectoryReader ireader = DirectoryReader.open(getIndexWriter(), false); + DirectoryReader ireader = DirectoryReader.open(getLuceneUtils().getIndexWriter(), false); IndexSearcher isearcher = new IndexSearcher(ireader); String[] words = text.split(" "); @@ -123,7 +110,7 @@ public class DocumentsIndexationService extends CoselmarSimpleServiceSupport { } public void updateDocument(DocumentBean document) throws IOException { - DirectoryReader ireader = DirectoryReader.open(getIndexWriter(), false); + DirectoryReader ireader = DirectoryReader.open(getLuceneUtils().getIndexWriter(), false); IndexSearcher isearcher = new IndexSearcher(ireader); // Retrieve document @@ -148,9 +135,11 @@ public class DocumentsIndexationService extends CoselmarSimpleServiceSupport { doc.add(new Field(DOCUMENT_KEYWORD_INDEX_PROPERTY, keyword, TextField.TYPE_STORED)); } - getIndexWriter().updateDocument(new Term(DOCUMENT_ID_INDEX_PROPERTY, document.getId()), doc); - getIndexWriter().commit(); + getLuceneUtils().getIndexWriter().updateDocument(new Term(DOCUMENT_ID_INDEX_PROPERTY, document.getId()), doc); + getLuceneUtils().getIndexWriter().commit(); } + + ireader.close(); } public void deleteDocument(String documentId) throws IOException { @@ -160,35 +149,17 @@ public class DocumentsIndexationService extends CoselmarSimpleServiceSupport { query.add(new TermQuery(new Term(DOCUMENT_ID_INDEX_PROPERTY, documentId)), BooleanClause.Occur.MUST); query.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); - getIndexWriter().deleteDocuments(query); - getIndexWriter().commit(); + getLuceneUtils().getIndexWriter().deleteDocuments(query); + getLuceneUtils().getIndexWriter().commit(); } protected void cleanIndex() throws IOException { - getIndexWriter().deleteAll(); - getIndexWriter().commit(); - } - - protected static Analyzer getAnalyzer() { - if (analyzer == null) { -// analyzer = new StandardAnalyzer(); - //Use simple analyzer to index all words and be able to search with "close word" classified in StandardAnalyzer - analyzer = new SimpleAnalyzer(); - } - return analyzer; - + BooleanQuery query = new BooleanQuery(); + query.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); + getLuceneUtils().getIndexWriter().deleteDocuments(query); + getLuceneUtils().getIndexWriter().commit(); } - protected IndexWriter getIndexWriter() throws IOException { - if (indexWriter == null) { - File indexDirectory = getCoselmarServicesConfig().getIndexDirectory(); - Directory index = NIOFSDirectory.open(indexDirectory); - - indexationConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); - indexWriter = new IndexWriter(index, indexationConfig); - } - return indexWriter; - } } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java new file mode 100644 index 0000000..5eeff68 --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java @@ -0,0 +1,51 @@ +package fr.ifremer.coselmar.services.indexation; + +import java.io.File; +import java.io.IOException; + +import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.core.SimpleAnalyzer; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.NIOFSDirectory; +import org.apache.lucene.util.Version; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class LuceneUtils { + + public static Analyzer analyzer; + public static final IndexWriterConfig indexationConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, getAnalyzer()); + public static IndexWriter indexWriter; + + protected CoselmarServicesConfig servicesConfig; + + public LuceneUtils(CoselmarServicesConfig servicesConfig) { + this.servicesConfig = servicesConfig; + } + + protected static Analyzer getAnalyzer() { + if (analyzer == null) { +// analyzer = new StandardAnalyzer(); + //Use simple analyzer to index all words and be able to search with "close word" classified in StandardAnalyzer + analyzer = new SimpleAnalyzer(); + } + return analyzer; + + } + + public IndexWriter getIndexWriter() throws IOException { + if (indexWriter == null) { + File indexDirectory = servicesConfig.getIndexDirectory(); + Directory index = NIOFSDirectory.open(indexDirectory); + + indexationConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); + indexWriter = new IndexWriter(index, indexationConfig); + } + return indexWriter; + } + +} diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationService.java new file mode 100644 index 0000000..178c9b4 --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationService.java @@ -0,0 +1,161 @@ +package fr.ifremer.coselmar.services.indexation; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import fr.ifremer.coselmar.beans.QuestionBean; +import fr.ifremer.coselmar.services.CoselmarSimpleServiceSupport; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.StringField; +import org.apache.lucene.document.TextField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.TermQuery; + +/** + * This Services provides operation about {@link fr.ifremer.coselmar.persistence.entity.Document} + * or more exactly {@link fr.ifremer.coselmar.beans.DocumentBean} indexation : + * <ul> + * <li>registration of a document in the indexation db</li> + * <li>modification of a document in the indexation db</li> + * <li>documents search from the indexation db</li> + * </ul> + * + * The purpose is to use power of a indexation db (lucene) to increase search on + * document text field, and make easier fulltext search + * + * @author ymartel <martel@codelutin.com> + */ +public class QuestionsIndexationService extends CoselmarSimpleServiceSupport { + + protected static final String QUESTION_ID_INDEX_PROPERTY = "questionId"; + protected static final String QUESTION_TITLE_INDEX_PROPERTY = "questionTitle"; + protected static final String QUESTION_SUMMARY_INDEX_PROPERTY = "questionSummary"; + protected static final String QUESTION_THEME_INDEX_PROPERTY = "questionTheme"; + protected static final String DOCUMENT_TYPE = "question"; + + public void indexQuestion(QuestionBean question) throws IOException { + + Document doc = new Document(); + doc.add(new StringField(QUESTION_ID_INDEX_PROPERTY, question.getId(), Field.Store.YES)); + + doc.add(new TextField(QUESTION_TITLE_INDEX_PROPERTY, question.getTitle(), Field.Store.YES)); + doc.add(new TextField(QUESTION_SUMMARY_INDEX_PROPERTY, question.getSummary(), Field.Store.YES)); + doc.add(new Field("type", DOCUMENT_TYPE, TextField.TYPE_STORED)); + + Set<String> themes = question.getThemes(); + for (String theme : themes) { + doc.add(new Field(QUESTION_THEME_INDEX_PROPERTY, theme, TextField.TYPE_STORED)); + } + + + getLuceneUtils().getIndexWriter().addDocument(doc); + getLuceneUtils().getIndexWriter().commit(); + + } + + public List<String> searchQuestion(String text) throws IOException, ParseException { + DirectoryReader ireader = DirectoryReader.open(getLuceneUtils().getIndexWriter(), false); + IndexSearcher isearcher = new IndexSearcher(ireader); + + String[] words = text.replaceAll("[^a-zA-Z ]", "").toLowerCase().split(" "); + + // Parse a simple query that searches for the "text": + BooleanQuery query = new BooleanQuery(); + + PhraseQuery nameQuery = new PhraseQuery(); + PhraseQuery summaryQuery = new PhraseQuery(); + PhraseQuery authorsQuery = new PhraseQuery(); + + for (String word : words) { + nameQuery.add(new Term(QUESTION_TITLE_INDEX_PROPERTY, word.toLowerCase())); + summaryQuery.add(new Term(QUESTION_SUMMARY_INDEX_PROPERTY, word.toLowerCase())); + } + + query.add(nameQuery, BooleanClause.Occur.SHOULD); + query.add(summaryQuery, BooleanClause.Occur.SHOULD); + query.add(authorsQuery, BooleanClause.Occur.SHOULD); + + query.add(new TermQuery(new Term(QUESTION_THEME_INDEX_PROPERTY, text.toLowerCase())), BooleanClause.Occur.SHOULD); + + + // Combine that with the type + BooleanQuery fullQuery = new BooleanQuery(); + fullQuery.add(query, BooleanClause.Occur.MUST); + fullQuery.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); + + ScoreDoc[] hits = isearcher.search(fullQuery, null, 1000).scoreDocs; + + List<String> documentIds = new ArrayList(hits.length); + + for (ScoreDoc hit : hits) { + Document doc = isearcher.doc(hit.doc); + String documentId = doc.get(QUESTION_ID_INDEX_PROPERTY); + documentIds.add(documentId); + } + + ireader.close(); + return documentIds; + } + + public void updateQuestion(QuestionBean question) throws IOException { + DirectoryReader ireader = DirectoryReader.open(getLuceneUtils().getIndexWriter(), false); + IndexSearcher isearcher = new IndexSearcher(ireader); + + // Retrieve document + BooleanQuery query = new BooleanQuery(); + query.add(new TermQuery(new Term(QUESTION_ID_INDEX_PROPERTY, question.getId())), BooleanClause.Occur.MUST); + query.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); + + ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs; + if (hits.length > 0) { + Document doc = isearcher.doc(hits[0].doc); + + doc.removeField(QUESTION_TITLE_INDEX_PROPERTY); + doc.add(new TextField(QUESTION_TITLE_INDEX_PROPERTY, question.getTitle(), Field.Store.YES)); + doc.removeField(QUESTION_SUMMARY_INDEX_PROPERTY); + doc.add(new TextField(QUESTION_SUMMARY_INDEX_PROPERTY, question.getSummary(), Field.Store.YES)); + + doc.removeFields(QUESTION_THEME_INDEX_PROPERTY); + Set<String> themes = question.getThemes(); + for (String theme : themes) { + doc.add(new Field(QUESTION_THEME_INDEX_PROPERTY, theme, TextField.TYPE_STORED)); + } + + getLuceneUtils().getIndexWriter().updateDocument(new Term(QUESTION_ID_INDEX_PROPERTY, question.getId()), doc); + getLuceneUtils().getIndexWriter().commit(); + } + + ireader.close(); + } + + public void deleteQuestion(String documentId) throws IOException { + + // Retrieve document + BooleanQuery query = new BooleanQuery(); + query.add(new TermQuery(new Term(QUESTION_ID_INDEX_PROPERTY, documentId)), BooleanClause.Occur.MUST); + query.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); + + getLuceneUtils().getIndexWriter().deleteDocuments(query); + getLuceneUtils().getIndexWriter().commit(); + + } + + protected void cleanIndex() throws IOException { + BooleanQuery query = new BooleanQuery(); + query.add(new TermQuery(new Term("type", DOCUMENT_TYPE)), BooleanClause.Occur.MUST); + getLuceneUtils().getIndexWriter().deleteDocuments(query); + getLuceneUtils().getIndexWriter().commit(); + } + + +} diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationServiceTest.java index 7b667a3..251c084 100644 --- a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationServiceTest.java +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/DocumentsIndexationServiceTest.java @@ -19,13 +19,13 @@ import org.junit.Test; */ public class DocumentsIndexationServiceTest extends AbstractCoselmarServiceTest { -// protected FakeCoselmarServicesContext serviceContext; + protected FakeCoselmarServicesContext serviceContext; protected FakeCoselmarServicesContext getServiceContext() { -// if (serviceContext == null) { - FakeCoselmarServicesContext serviceContext = application.newServiceContext(application.newPersistenceContext(), Locale.FRANCE); -// } + if (serviceContext == null) { + serviceContext = application.newServiceContext(application.newPersistenceContext(), Locale.FRANCE); + } return serviceContext; } diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationServiceTest.java new file mode 100644 index 0000000..fff64be --- /dev/null +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/indexation/QuestionsIndexationServiceTest.java @@ -0,0 +1,271 @@ +package fr.ifremer.coselmar.services.indexation; + +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import com.google.common.collect.Sets; +import fr.ifremer.coselmar.beans.QuestionBean; +import fr.ifremer.coselmar.persistence.entity.Privacy; +import fr.ifremer.coselmar.persistence.entity.Status; +import fr.ifremer.coselmar.services.AbstractCoselmarServiceTest; +import fr.ifremer.coselmar.services.CoselmarServicesContext; +import fr.ifremer.coselmar.services.FakeCoselmarServicesContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.util.DateUtil; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class QuestionsIndexationServiceTest extends AbstractCoselmarServiceTest { + + protected FakeCoselmarServicesContext serviceContext; + + protected FakeCoselmarServicesContext getServiceContext() { + + if (this.serviceContext == null) { + this.serviceContext = application.newServiceContext(application.newPersistenceContext(), Locale.FRANCE); + } + + return this.serviceContext; + } + + @Test + public void testAddQuestion() throws Exception { + CoselmarServicesContext serviceContext = getServiceContext(); + QuestionsIndexationService questionsIndexationService = + serviceContext.newService(QuestionsIndexationService.class); + + QuestionBean question = new QuestionBean(); + question.setTitle("Awesome question"); + question.setSummary("Can we, just once, ask about it ?"); + question.setDeadline(DateUtil.createDateAfterToday(1, 1, 1)); + question.setExternalExperts(Sets.newHashSet("Amelia", "Rory", "River")); + question.setSubmissionDate(new Date()); + question.setStatus(Status.OPEN.name()); + question.setPrivacy(Privacy.PUBLIC.name()); + question.setThemes(Sets.newHashSet("TARDIS", "Universe", "Time", "Space")); + question.setId("question_" + System.currentTimeMillis()); + + questionsIndexationService.indexQuestion(question); + + } + + @Test + public void testSearchQuestion() throws Exception { + + QuestionBean questionOne = new QuestionBean(); + String questionOneId = "question_1_test_search" + System.currentTimeMillis(); + questionOne.setId(questionOneId); + questionOne.setTitle("Awesome question"); + questionOne.setSummary("Can we, just once, ask about it ?"); + questionOne.setDeadline(DateUtil.createDateAfterToday(1, 0, 1)); + questionOne.setExternalExperts(Sets.newHashSet("Amelia", "Rory", "River")); + questionOne.setSubmissionDate(new Date()); + questionOne.setStatus(Status.OPEN.name()); + questionOne.setPrivacy(Privacy.PUBLIC.name()); + questionOne.setThemes(Sets.newHashSet("TARDIS", "Universe", "Time", "Space")); + + QuestionBean questionTwo = new QuestionBean(); + String questionTwoId = "question_2_test_search" + System.currentTimeMillis(); + questionTwo.setId(questionTwoId); + questionTwo.setTitle("The ultimate"); + questionTwo.setSummary("We need some question"); + questionTwo.setDeadline(DateUtil.createDateAfterToday(16, 0, 0)); + questionTwo.setSubmissionDate(new Date()); + questionTwo.setStatus(Status.OPEN.name()); + questionTwo.setPrivacy(Privacy.PUBLIC.name()); + questionTwo.setThemes(Sets.newHashSet("test", "question")); + + QuestionBean questionThree = new QuestionBean(); + String questionThreeId = "question_3_test_search" + System.currentTimeMillis(); + questionThree.setId(questionThreeId); + questionThree.setTitle("There's someone missing. The question's Who?"); + questionThree.setSummary("Something old, Something new, Something borrowed, Something blue."); + questionThree.setDeadline(DateUtil.createDateAfterToday(16, 0, 0)); + questionThree.setSubmissionDate(new Date()); + questionThree.setStatus(Status.OPEN.name()); + questionThree.setPrivacy(Privacy.PUBLIC.name()); + questionThree.setThemes(Sets.newHashSet("big bang two", "Pandorica", "River", "Universe")); + + + CoselmarServicesContext serviceContext = getServiceContext(); + QuestionsIndexationService questionsIndexationService = + serviceContext.newService(QuestionsIndexationService.class); + + questionsIndexationService.indexQuestion(questionOne); + questionsIndexationService.indexQuestion(questionTwo); + questionsIndexationService.indexQuestion(questionThree); + + // Ok, let's search now ! + List<String> questionMatchingTitleIds = questionsIndexationService.searchQuestion("ultimate"); + Assert.assertEquals(1, questionMatchingTitleIds.size()); + Assert.assertEquals(questionTwoId, questionMatchingTitleIds.get(0)); + + List<String> questionMatchingAmyIds = questionsIndexationService.searchQuestion("amy"); + Assert.assertTrue(questionMatchingAmyIds.isEmpty()); + + List<String> questionMatchingPandoricaIds = questionsIndexationService.searchQuestion("Pandorica"); + Assert.assertEquals(1, questionMatchingPandoricaIds.size()); + Assert.assertEquals(questionThreeId, questionMatchingPandoricaIds.get(0)); + + List<String> questionMatchingUniverseIds = questionsIndexationService.searchQuestion("universe"); + Assert.assertEquals(2, questionMatchingUniverseIds.size()); + Assert.assertTrue(questionMatchingUniverseIds.contains(questionThreeId)); + Assert.assertTrue(questionMatchingUniverseIds.contains(questionOneId)); + + List<String> documentMatchingUnknownIds = questionsIndexationService.searchQuestion("Unknown"); + Assert.assertTrue(documentMatchingUnknownIds.isEmpty()); + + List<String> documentMatchingPartOfSummaryIds = questionsIndexationService.searchQuestion("Something blue"); + Assert.assertEquals(1, documentMatchingPartOfSummaryIds.size()); + Assert.assertEquals(questionThreeId, documentMatchingPartOfSummaryIds.get(0)); + + documentMatchingPartOfSummaryIds = questionsIndexationService.searchQuestion("Something borrowed,"); + Assert.assertEquals(1, documentMatchingPartOfSummaryIds.size()); + Assert.assertEquals(questionThreeId, documentMatchingPartOfSummaryIds.get(0)); + + documentMatchingPartOfSummaryIds = questionsIndexationService.searchQuestion("can we"); + Assert.assertEquals(1, documentMatchingPartOfSummaryIds.size()); + Assert.assertEquals(questionOneId, documentMatchingPartOfSummaryIds.get(0)); + + } + + @Test + public void testUpdateQuestion() throws Exception { + + QuestionBean questionOne = new QuestionBean(); + String questionOneId = "question_1_test_update_" + System.currentTimeMillis(); + questionOne.setId(questionOneId); + questionOne.setTitle("Awesome question"); + questionOne.setSummary("Can we, just once, ask about it ?"); + questionOne.setDeadline(DateUtil.createDateAfterToday(1, 0, 1)); + questionOne.setExternalExperts(Sets.newHashSet("Amelia", "Rory", "River")); + questionOne.setSubmissionDate(new Date()); + questionOne.setStatus(Status.OPEN.name()); + questionOne.setPrivacy(Privacy.PUBLIC.name()); + questionOne.setThemes(Sets.newHashSet("TARDIS", "Universe", "Time", "Space")); + + QuestionBean questionTwo = new QuestionBean(); + String questionTwoId = "question_2_test_update_" + System.currentTimeMillis(); + questionTwo.setId(questionTwoId); + questionTwo.setTitle("There's someone missing. The question's Who?"); + questionTwo.setSummary("Something old, Something new, Something borrowed, Something blue."); + questionTwo.setDeadline(DateUtil.createDateAfterToday(16, 0, 0)); + questionTwo.setSubmissionDate(new Date()); + questionTwo.setStatus(Status.OPEN.name()); + questionTwo.setPrivacy(Privacy.PUBLIC.name()); + questionTwo.setThemes(Sets.newHashSet("big bang two", "Pandorica", "River", "Universe")); + + + CoselmarServicesContext serviceContext = getServiceContext(); + QuestionsIndexationService questionsIndexationService = + serviceContext.newService(QuestionsIndexationService.class); + + questionsIndexationService.indexQuestion(questionOne); + questionsIndexationService.indexQuestion(questionTwo); + + questionOne.setTitle("How old is the doctor who ?"); + questionsIndexationService.updateQuestion(questionOne); + + // Ok, let's search now ! + List<String> questionMatchingTitleIds = questionsIndexationService.searchQuestion("awesome"); + Assert.assertTrue(questionMatchingTitleIds.isEmpty()); + + questionMatchingTitleIds = questionsIndexationService.searchQuestion("who"); + Assert.assertEquals(2, questionMatchingTitleIds.size()); + Assert.assertTrue(questionMatchingTitleIds.contains(questionOneId)); + Assert.assertTrue(questionMatchingTitleIds.contains(questionTwoId)); + + questionMatchingTitleIds = questionsIndexationService.searchQuestion("doctor"); + Assert.assertEquals(1, questionMatchingTitleIds.size()); + Assert.assertTrue(questionMatchingTitleIds.contains(questionOneId)); + + } + + @Test + public void testDeleteQuestion() throws Exception { + + QuestionBean questionOne = new QuestionBean(); + String questionOneId = "question_1_test_delete_" + System.currentTimeMillis(); + questionOne.setId(questionOneId); + questionOne.setTitle("Awesome question"); + questionOne.setSummary("Can we, just once, ask about it ?"); + questionOne.setDeadline(DateUtil.createDateAfterToday(1, 0, 1)); + questionOne.setExternalExperts(Sets.newHashSet("Amelia", "Rory", "River")); + questionOne.setSubmissionDate(new Date()); + questionOne.setStatus(Status.OPEN.name()); + questionOne.setPrivacy(Privacy.PUBLIC.name()); + questionOne.setThemes(Sets.newHashSet("TARDIS", "Universe", "Time", "Space")); + + QuestionBean questionTwo = new QuestionBean(); + String questionTwoId = "question_2_test_delete_" + System.currentTimeMillis(); + questionTwo.setId(questionTwoId); + questionTwo.setTitle("There's someone missing. The question's Who?"); + questionTwo.setSummary("Something old, Something new, Something borrowed, Something blue."); + questionTwo.setDeadline(DateUtil.createDateAfterToday(16, 0, 0)); + questionTwo.setSubmissionDate(new Date()); + questionTwo.setStatus(Status.OPEN.name()); + questionTwo.setPrivacy(Privacy.PUBLIC.name()); + questionTwo.setThemes(Sets.newHashSet("big bang two", "Pandorica", "River", "Universe")); + + + CoselmarServicesContext serviceContext = getServiceContext(); + QuestionsIndexationService questionsIndexationService = + serviceContext.newService(QuestionsIndexationService.class); + + questionsIndexationService.indexQuestion(questionOne); + questionsIndexationService.indexQuestion(questionTwo); + + // Ok, let's search now ! + List<String> questionMatchingTitleIds = questionsIndexationService.searchQuestion("awesome"); + Assert.assertEquals(1, questionMatchingTitleIds.size()); + Assert.assertEquals(questionOneId, questionMatchingTitleIds.get(0)); + + questionMatchingTitleIds = questionsIndexationService.searchQuestion("missing"); + Assert.assertEquals(1, questionMatchingTitleIds.size()); + Assert.assertEquals(questionTwoId, questionMatchingTitleIds.get(0)); + + List<String> questionMatchingUniverseIds = questionsIndexationService.searchQuestion("universe"); + Assert.assertEquals(2, questionMatchingUniverseIds.size()); + Assert.assertTrue(questionMatchingUniverseIds.contains(questionOneId)); + Assert.assertTrue(questionMatchingUniverseIds.contains(questionTwoId)); + + // Ok, this was already tested as ok, let's delete questionOne + questionsIndexationService.deleteQuestion(questionOneId); + + // and let's search same now ! + questionMatchingTitleIds = questionsIndexationService.searchQuestion("awesome"); + Assert.assertTrue(questionMatchingTitleIds.isEmpty()); + + questionMatchingTitleIds = questionsIndexationService.searchQuestion("missing"); + Assert.assertEquals(1, questionMatchingTitleIds.size()); + Assert.assertTrue(questionMatchingTitleIds.contains(questionTwoId)); + + questionMatchingUniverseIds = questionsIndexationService.searchQuestion("universe"); + Assert.assertEquals(1, questionMatchingUniverseIds.size()); + Assert.assertTrue(questionMatchingUniverseIds.contains(questionTwoId)); + + + List<String> documentMatchingPartOfSummaryIds = questionsIndexationService.searchQuestion("can we"); + Assert.assertTrue(documentMatchingPartOfSummaryIds.isEmpty()); + + documentMatchingPartOfSummaryIds = questionsIndexationService.searchQuestion("Something blue"); + Assert.assertEquals(1, documentMatchingPartOfSummaryIds.size()); + Assert.assertEquals(questionTwoId, documentMatchingPartOfSummaryIds.get(0)); + + + } + + @Before + public void cleanUp() throws Exception { + CoselmarServicesContext serviceContext = getServiceContext(); + QuestionsIndexationService questionsIndexationService = + serviceContext.newService(QuestionsIndexationService.class); + + questionsIndexationService.cleanIndex(); + + } +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.