1 /*****************************************************************************
5 * Creation date 05.10.2012
8 *****************************************************************************/
10 package org.splat.service;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.apache.log4j.Logger;
19 import org.apache.lucene.index.Term;
20 import org.apache.lucene.search.BooleanClause;
21 import org.apache.lucene.search.BooleanFilter;
22 import org.apache.lucene.search.BooleanQuery;
23 import org.apache.lucene.search.FilterClause;
24 import org.apache.lucene.search.IndexSearcher;
25 import org.apache.lucene.search.ScoreDoc;
26 import org.apache.lucene.search.Sort;
27 import org.apache.lucene.search.SortField;
28 import org.apache.lucene.search.TermQuery;
29 import org.apache.lucene.search.TermsFilter;
30 import org.apache.lucene.search.TopFieldDocs;
31 import org.apache.lucene.store.Directory;
32 import org.apache.lucene.store.FSDirectory;
33 import org.splat.dal.bo.kernel.User;
34 import org.splat.dal.bo.som.KnowledgeElement;
35 import org.splat.dal.bo.som.KnowledgeElementType;
36 import org.splat.dal.bo.som.ProgressState;
37 import org.splat.dal.bo.som.Scenario;
38 import org.splat.dal.bo.som.SimulationContext;
39 import org.splat.dal.bo.som.Study;
40 import org.splat.dal.bo.som.Visibility;
41 import org.splat.service.dto.Proxy;
42 import org.splat.service.technical.IndexService;
43 import org.splat.service.technical.IndexServiceImpl;
44 import org.splat.service.technical.RepositoryService;
45 import org.springframework.transaction.annotation.Transactional;
48 * Search service implementation.
50 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
52 public class SearchServiceImpl implements SearchService {
57 public final static Logger logger = Logger
58 .getLogger(org.splat.service.SearchServiceImpl.class);
61 * Injected repository service.
63 private RepositoryService _repositoryService;
65 * Injected index service.
67 private IndexService _indexService;
70 * Injected study service.
72 private StudyService _studyService;
75 * Refresh lucene index for studies.
78 * list of studies id's
80 @Transactional(readOnly = true)
81 public void reindexStudies(String[] ridlist) {
82 for (int i = 0; i < ridlist.length; i++) {
83 long index = Long.valueOf(ridlist[i].trim());
84 Study study = getStudyService().selectStudy(index);
92 * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.dal.bo.som.KnowledgeElement.Properties[])
94 public List<Proxy> selectKnowledgeElementsWhere(
95 KnowledgeElement.Properties... kprop) {
96 List<Proxy> result = new ArrayList<Proxy>();
100 // Creation of the Lucene query
101 File indir = getRepositoryService().getRepositoryIndexDirectory();
102 Directory index = FSDirectory.open(indir);
103 IndexSearcher searcher = new IndexSearcher(index, true);
104 BooleanQuery fulquery = new BooleanQuery();
106 for (int i = 0; i < kprop.length; i++) {
107 BooleanQuery query = new BooleanQuery();
108 Term input; // Supposed initialized below at least by the visibility
110 Visibility area = kprop[i].getVisibility(); // Visibility
112 input = new Term("area");
113 query.add(new TermQuery(input.createTerm(area.toString())),
114 BooleanClause.Occur.MUST);
116 ProgressState state = kprop[i].getProgressState(); // State
118 input = new Term("state");
120 new TermQuery(input.createTerm(state.toString())),
121 BooleanClause.Occur.MUST);
123 String refid = kprop[i].getReference(); // Reference
125 input = new Term("ref");
126 query.add(new TermQuery(input.createTerm(refid)),
127 BooleanClause.Occur.MUST);
129 KnowledgeElementType type = kprop[i].getType(); // Type
131 input = new Term("type");
132 query.add(new TermQuery(input.createTerm(type.getName())),
133 BooleanClause.Occur.MUST);
135 User manager = kprop[i].getAuthor(); // Author
136 if (manager != null) {
137 input = new Term("author");
138 query.add(new TermQuery(input
139 .createTerm(manager.toString())),
140 BooleanClause.Occur.MUST);
142 User actor = kprop[i].getActor(); // Contributor, Reviewer or Approver of the owner study
144 input = new Term("actor");
146 new TermQuery(input.createTerm(actor.toString())),
147 BooleanClause.Occur.MUST);
149 String title = kprop[i].getTitle(); // Title
151 input = new Term("contents");
152 BooleanQuery critext = new BooleanQuery();
153 String operator = "AND"; // Future user input
154 BooleanClause.Occur clause = BooleanClause.Occur.MUST;
155 if (operator.equals("OR"))
156 clause = BooleanClause.Occur.SHOULD;
157 String[] word = title.split(" ");
158 for (int j = 0; j < word.length; j++) {
159 critext.add(new TermQuery(input.createTerm(word[j])),
162 query.add(critext, BooleanClause.Occur.MUST);
164 List<SimulationContext> context = kprop[i]
165 .getSimulationContexts();
166 if (context != null && context.size() > 0) {
167 BooleanQuery critext = new BooleanQuery();
168 for (Iterator<SimulationContext> j = context.iterator(); j
170 SimulationContext seltext = j.next();
171 input = new Term(String.valueOf(seltext.getType()
173 critext.add(new TermQuery(input.createTerm(seltext
174 .getValue())), BooleanClause.Occur.MUST);
176 query.add(critext, BooleanClause.Occur.MUST);
178 fulquery.add(query, BooleanClause.Occur.SHOULD);
180 if (logger.isInfoEnabled()) {
181 logger.info("Searching knowledges by Lucene query \""
182 + fulquery.toString() + "\".");
184 // Creation of the knowledge filter
185 BooleanFilter filter = new BooleanFilter();
186 TermsFilter select = new TermsFilter();
187 Term mytype = new Term("class");
188 select.addTerm(mytype.createTerm("KnowledgeElement"));
189 filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
191 // Creation of the sort criteria
192 Sort sort = new Sort(new SortField("title", SortField.STRING));
195 TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
198 if (found.totalHits < 1)
199 return result; // No study found
201 // Construction of the result list
202 ScoreDoc[] hits = found.scoreDocs;
203 for (int i = 0; i < hits.length; i++) {
204 result.add(new IndexServiceImpl.ObjectProxy(searcher
208 } catch (Exception error) {
209 logger.error("Error during Lucene search, reason:", error);
217 * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.dal.bo.som.Study.Properties[])
219 public List<Proxy> selectStudiesWhere(Study.Properties... sprop) {
220 List<Proxy> result = new ArrayList<Proxy>();
224 // Creation of the Lucene query
225 File indir = getRepositoryService().getRepositoryIndexDirectory();
226 Directory index = FSDirectory.open(indir);
227 IndexSearcher searcher = new IndexSearcher(index, true);
228 BooleanQuery fulquery = new BooleanQuery();
230 for (int i = 0; i < sprop.length; i++) {
231 BooleanQuery query = new BooleanQuery();
232 Term input; // Supposed initialized below at least by the visibility
234 Visibility area = sprop[i].getVisibility(); // Visibility
236 input = new Term("area");
237 query.add(new TermQuery(input.createTerm(area.toString())),
238 BooleanClause.Occur.MUST);
240 ProgressState state = sprop[i].getProgressState(); // State
242 input = new Term("state");
243 if (state == ProgressState.inPROGRESS) {
244 BooleanQuery cristate = new BooleanQuery();
245 cristate.add(new TermQuery(input.createTerm("inWORK")),
246 BooleanClause.Occur.SHOULD);
248 new TermQuery(input.createTerm("inDRAFT")),
249 BooleanClause.Occur.SHOULD);
251 new TermQuery(input.createTerm("inCHECK")),
252 BooleanClause.Occur.SHOULD);
253 query.add(cristate, BooleanClause.Occur.MUST);
255 query.add(new TermQuery(input.createTerm(state
256 .toString())), BooleanClause.Occur.MUST);
259 String refid = sprop[i].getReference(); // Reference
261 input = new Term("ref");
262 query.add(new TermQuery(input.createTerm(refid)),
263 BooleanClause.Occur.MUST);
265 User manager = sprop[i].getManager(); // Author
266 if (manager != null) {
267 input = new Term("author");
268 query.add(new TermQuery(input
269 .createTerm(manager.toString())),
270 BooleanClause.Occur.MUST);
272 User actor = sprop[i].getActor(); // Contributor, Reviewer or Approver
274 input = new Term("actor");
276 new TermQuery(input.createTerm(actor.toString())),
277 BooleanClause.Occur.MUST);
279 String title = sprop[i].getTitle(); // Title
281 input = new Term("contents");
282 BooleanQuery critext = new BooleanQuery();
283 String operator = "AND"; // Future user input
284 BooleanClause.Occur clause = BooleanClause.Occur.MUST;
285 if (operator.equals("OR"))
286 clause = BooleanClause.Occur.SHOULD;
287 String[] word = title.split(" ");
288 for (int j = 0; j < word.length; j++) {
289 critext.add(new TermQuery(input.createTerm(word[j])),
292 query.add(critext, BooleanClause.Occur.MUST);
294 List<SimulationContext> context = sprop[i]
295 .getSimulationContexts();
296 if (context != null && context.size() > 0) {
297 BooleanQuery critext = new BooleanQuery();
298 for (Iterator<SimulationContext> j = context.iterator(); j
300 SimulationContext seltext = j.next();
301 input = new Term(String.valueOf(seltext.getType()
303 critext.add(new TermQuery(input.createTerm(seltext
304 .getValue())), BooleanClause.Occur.MUST);
306 query.add(critext, BooleanClause.Occur.MUST);
308 fulquery.add(query, BooleanClause.Occur.SHOULD);
310 if (logger.isInfoEnabled()) {
311 logger.info("Searching studies by Lucene query \""
312 + fulquery.toString() + "\".");
314 // Creation of the studies filter
315 BooleanFilter filter = new BooleanFilter();
316 TermsFilter select = new TermsFilter();
317 Term mytype = new Term("class");
318 select.addTerm(mytype.createTerm("Study"));
319 filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
321 // Creation of the sort criteria
322 Sort sort = new Sort(new SortField("title", SortField.STRING));
325 TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
328 if (found.totalHits < 1)
329 return result; // No study found
331 // Construction of the result list
332 ScoreDoc[] hits = found.scoreDocs;
333 for (int i = 0; i < hits.length; i++) {
334 result.add(new IndexServiceImpl.ObjectProxy(searcher
338 } catch (Exception error) {
339 logger.error("Error during Lucene search, reason:", error);
347 * @see org.splat.service.SearchService#indexStudy(org.splat.dal.bo.som.Study)
349 public void indexStudy(Study study) {
350 logger.debug("Index study: id=" + study.getRid() + "; reference=" + study.getReference());
352 Study.Properties sprop = new Study.Properties();
353 List<Proxy> index = selectStudiesWhere(sprop.setReference(study
356 if (index.size() != 0) {
357 logger.debug("The given study is already indexed.");
358 return; // The given study is already indexed
361 IndexService lucin = getIndex();
362 Scenario[] scenes = study.getScenarii();
364 logger.debug("Number of study " + study.getReference() + " actors: " + study.getActor().size());
366 if (study.getProgressState() != ProgressState.inWORK)
367 for (int i = 0; i < scenes.length; i++) {
368 List<KnowledgeElement> list = scenes[i]
369 .getAllKnowledgeElements();
370 for (Iterator<KnowledgeElement> j = list.iterator(); j
373 logger.debug("Knowlegge added: id=" + j.next().getIndex());
376 } catch (Exception error) {
377 logger.error("Unable to index the study '"
378 + study.getIndex() + "', reason:", error);
383 * Get lucene index handler. Create the index if it is not exist.
385 * @return IndexService
386 * @throws IOException
387 * if error when creating a new lucene index
389 private IndexService getIndex() throws IOException {
390 IndexService lucin = getIndexService();
392 lucin.create(); // Happens when re-indexing all studies
397 * Get the repositoryService.
399 * @return the repositoryService
401 public RepositoryService getRepositoryService() {
402 return _repositoryService;
406 * Set the repositoryService.
408 * @param repositoryService
409 * the repositoryService to set
411 public void setRepositoryService(RepositoryService repositoryService) {
412 _repositoryService = repositoryService;
416 * Get the indexService.
418 * @return the indexService
420 public IndexService getIndexService() {
421 return _indexService;
425 * Set the indexService.
427 * @param indexService
428 * the indexService to set
430 public void setIndexService(IndexService indexService) {
431 _indexService = indexService;
435 * Get the studyService.
436 * @return the studyService
438 public StudyService getStudyService() {
439 return _studyService;
443 * Set the studyService.
444 * @param studyService the studyService to set
446 public void setStudyService(StudyService studyService) {
447 _studyService = studyService;