Salome HOME
Modifications done to respect PMD rules. Versioning a document is fixed. Validation...
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / SearchServiceImpl.java
1 /*****************************************************************************
2  * Company         OPEN CASCADE
3  * Application     SIMAN
4  * File            $Id$ 
5  * Creation date   05.10.2012
6  * @author         $Author$
7  * @version        $Revision$
8  *****************************************************************************/
9
10 package org.splat.service;
11
12 import java.io.File;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17
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.dal.dao.som.StudyDAO;
42 import org.splat.service.dto.ImportedStudyDTO;
43 import org.splat.service.dto.Proxy;
44 import org.splat.service.technical.IndexService;
45 import org.splat.service.technical.IndexServiceImpl;
46 import org.splat.service.technical.RepositoryService;
47 import org.splat.util.BeanHelper;
48 import org.springframework.transaction.annotation.Transactional;
49
50 /**
51  * Search service implementation.
52  * 
53  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
54  */
55 public class SearchServiceImpl implements SearchService {
56
57         /**
58          * The service logger.
59          */
60         public final static Logger LOG = Logger
61                         .getLogger(org.splat.service.SearchServiceImpl.class);
62
63         /**
64          * Injected repository service.
65          */
66         private RepositoryService _repositoryService;
67         /**
68          * Injected index service.
69          */
70         private IndexService _indexService;
71         /**
72          * Injected study service.
73          */
74         private StudyService _studyService;
75         /**
76          * Injected study DAO.
77          */
78         private StudyDAO _studyDAO;
79
80         /**
81          * Get a list of studies which are currently not presented in the lucene index.
82          * @return list of ImportedStudy DTO
83          */
84         @Transactional(readOnly=true)
85         public List<ImportedStudyDTO> selectStudies() {
86                 List<ImportedStudyDTO> table = new ArrayList<ImportedStudyDTO>();
87                 Study.Properties sprop = new Study.Properties();
88                 List<Study> dbStudies = getStudyDAO().getAll();
89
90                 for (Study aStudy : dbStudies) {
91                         try {
92                                 sprop.clear();
93                                 if (selectStudiesWhere(
94                                                 sprop.setReference(aStudy.getReference())).size() != 0) {
95                                         // If this study was already indexed and found in the lucene index
96                                         // then skip it to avoid adding to the index it again.
97                                         continue;
98                                 }
99                         } catch (Exception error) {
100                                 continue;
101                         }
102                         // Add the study to the list of studies which are 
103                         // currently not presented in the lucene index.
104                         table.add(BeanHelper.copyBean(aStudy, ImportedStudyDTO.class));
105                 }
106                 return table;
107         }
108
109         /**
110          * Refresh lucene index for studies.
111          * 
112          * @param ridlist
113          *            list of studies id's
114          */
115         @Transactional(readOnly = true)
116         public void reindexStudies(final String[] ridlist) {
117                 for (int i = 0; i < ridlist.length; i++) {
118                         long index = Long.valueOf(ridlist[i].trim());
119                         Study study = getStudyService().selectStudy(index);
120                         indexStudy(study);
121                 }
122         }
123
124         /**
125          * {@inheritDoc}
126          * 
127          * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.dal.bo.som.KnowledgeElement.Properties[])
128          */
129         public List<Proxy> selectKnowledgeElementsWhere(
130                         final KnowledgeElement.Properties... kprop) {
131                 List<Proxy> result = new ArrayList<Proxy>();
132                 int hitsize = 20;
133                 try {
134
135                         // Creation of the Lucene query
136                         File indir = getRepositoryService().getRepositoryIndexDirectory();
137                         Directory index = FSDirectory.open(indir);
138                         IndexSearcher searcher = new IndexSearcher(index, true);
139                         BooleanQuery fulquery = new BooleanQuery();
140
141                         for (int i = 0; i < kprop.length; i++) {
142                                 BooleanQuery query = new BooleanQuery();
143                                 Term input; // Supposed initialized below at least by the visibility
144
145                                 Visibility area = kprop[i].getVisibility(); // Visibility
146                                 if (area != null) {
147                                         input = new Term("area");
148                                         query.add(new TermQuery(input.createTerm(area.toString())),
149                                                         BooleanClause.Occur.MUST);
150                                 }
151                                 ProgressState state = kprop[i].getProgressState(); // State
152                                 if (state != null) {
153                                         input = new Term("state");
154                                         query.add(
155                                                         new TermQuery(input.createTerm(state.toString())),
156                                                         BooleanClause.Occur.MUST);
157                                 }
158                                 String refid = kprop[i].getReference(); // Reference
159                                 if (refid != null) {
160                                         input = new Term("ref");
161                                         query.add(new TermQuery(input.createTerm(refid)),
162                                                         BooleanClause.Occur.MUST);
163                                 }
164                                 KnowledgeElementType type = kprop[i].getType(); // Type
165                                 if (type != null) {
166                                         input = new Term("type");
167                                         query.add(new TermQuery(input.createTerm(type.getName())),
168                                                         BooleanClause.Occur.MUST);
169                                 }
170                                 User manager = kprop[i].getAuthor(); // Author
171                                 if (manager != null) {
172                                         input = new Term("author");
173                                         query.add(new TermQuery(input
174                                                         .createTerm(manager.toString())),
175                                                         BooleanClause.Occur.MUST);
176                                 }
177                                 User actor = kprop[i].getActor(); // Contributor, Reviewer or Approver of the owner study
178                                 if (actor != null) {
179                                         input = new Term("actor");
180                                         query.add(
181                                                         new TermQuery(input.createTerm(actor.toString())),
182                                                         BooleanClause.Occur.MUST);
183                                 }
184                                 String title = kprop[i].getTitle(); // Title
185                                 if (title != null) {
186                                         input = new Term("contents");
187                                         BooleanQuery critext = new BooleanQuery();
188                                         String operator = "AND"; // Future user input
189                                         BooleanClause.Occur clause = BooleanClause.Occur.MUST;
190                                         if (operator.equals("OR")) {
191                                                 clause = BooleanClause.Occur.SHOULD;
192                                         }
193                                         String[] word = title.split(" ");
194                                         for (int j = 0; j < word.length; j++) {
195                                                 critext.add(new TermQuery(input.createTerm(word[j])),
196                                                                 clause);
197                                         }
198                                         query.add(critext, BooleanClause.Occur.MUST);
199                                 }
200                                 List<SimulationContext> context = kprop[i]
201                                                 .getSimulationContexts();
202                                 if (context != null && context.size() > 0) {
203                                         BooleanQuery critext = new BooleanQuery();
204                                         for (Iterator<SimulationContext> j = context.iterator(); j
205                                                         .hasNext();) {
206                                                 SimulationContext seltext = j.next();
207                                                 input = new Term(String.valueOf(seltext.getType()
208                                                                 .getIndex()));
209                                                 critext.add(new TermQuery(input.createTerm(seltext
210                                                                 .getValue())), BooleanClause.Occur.MUST);
211                                         }
212                                         query.add(critext, BooleanClause.Occur.MUST);
213                                 }
214                                 fulquery.add(query, BooleanClause.Occur.SHOULD);
215                         }
216                         if (LOG.isInfoEnabled()) {
217                                 LOG.info("Searching knowledges by Lucene query \""
218                                                 + fulquery.toString() + "\".");
219                         }
220                         // Creation of the knowledge filter
221                         BooleanFilter filter = new BooleanFilter();
222                         TermsFilter select = new TermsFilter();
223                         Term mytype = new Term("class");
224                         select.addTerm(mytype.createTerm("KnowledgeElement"));
225                         filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
226
227                         // Creation of the sort criteria
228                         Sort sort = new Sort(new SortField("title", SortField.STRING));
229
230                         // Search
231                         TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
232                                         sort);
233
234                         if (found.totalHits < 1) {
235                                 return result; // No study found
236                         }
237
238                         // Construction of the result list
239                         ScoreDoc[] hits = found.scoreDocs;
240                         for (int i = 0; i < hits.length; i++) {
241                                 result.add(new IndexServiceImpl.ObjectProxy(searcher
242                                                 .doc(hits[i].doc)));
243                         }
244                         searcher.close();
245                 } catch (Exception error) {
246                         LOG.error("Error during Lucene search, reason:", error);
247                 }
248                 return result;
249         }
250
251         /**
252          * {@inheritDoc}
253          * 
254          * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.dal.bo.som.Study.Properties[])
255          */
256         public List<Proxy> selectStudiesWhere(final Study.Properties... sprop) {
257                 List<Proxy> result = new ArrayList<Proxy>();
258                 int hitsize = 20;
259                 try {
260
261                         // Creation of the Lucene query
262                         File indir = getRepositoryService().getRepositoryIndexDirectory();
263                         Directory index = FSDirectory.open(indir);
264                         IndexSearcher searcher = new IndexSearcher(index, true);
265                         BooleanQuery fulquery = new BooleanQuery();
266
267                         for (int i = 0; i < sprop.length; i++) {
268                                 BooleanQuery query = new BooleanQuery();
269                                 Term input; // Supposed initialized below at least by the visibility
270
271                                 Visibility area = sprop[i].getVisibility(); // Visibility
272                                 if (area != null) {
273                                         input = new Term("area");
274                                         query.add(new TermQuery(input.createTerm(area.toString())),
275                                                         BooleanClause.Occur.MUST);
276                                 }
277                                 ProgressState state = sprop[i].getProgressState(); // State
278                                 if (state != null) {
279                                         input = new Term("state");
280                                         if (state == ProgressState.inPROGRESS) {
281                                                 BooleanQuery cristate = new BooleanQuery();
282                                                 cristate.add(new TermQuery(input.createTerm("inWORK")),
283                                                                 BooleanClause.Occur.SHOULD);
284                                                 cristate.add(
285                                                                 new TermQuery(input.createTerm("inDRAFT")),
286                                                                 BooleanClause.Occur.SHOULD);
287                                                 cristate.add(
288                                                                 new TermQuery(input.createTerm("inCHECK")),
289                                                                 BooleanClause.Occur.SHOULD);
290                                                 query.add(cristate, BooleanClause.Occur.MUST);
291                                         } else {
292                                                 query.add(new TermQuery(input.createTerm(state
293                                                                 .toString())), BooleanClause.Occur.MUST);
294                                         }
295                                 }
296                                 String refid = sprop[i].getReference(); // Reference
297                                 if (refid != null) {
298                                         input = new Term("ref");
299                                         query.add(new TermQuery(input.createTerm(refid)),
300                                                         BooleanClause.Occur.MUST);
301                                 }
302                                 User manager = sprop[i].getManager(); // Author
303                                 if (manager != null) {
304                                         input = new Term("author");
305                                         query.add(new TermQuery(input
306                                                         .createTerm(manager.toString())),
307                                                         BooleanClause.Occur.MUST);
308                                 }
309                                 User actor = sprop[i].getActor(); // Contributor, Reviewer or Approver
310                                 if (actor != null) {
311                                         input = new Term("actor");
312                                         query.add(
313                                                         new TermQuery(input.createTerm(actor.toString())),
314                                                         BooleanClause.Occur.MUST);
315                                 }
316                                 String title = sprop[i].getTitle(); // Title
317                                 if (title != null) {
318                                         input = new Term("contents");
319                                         BooleanQuery critext = new BooleanQuery();
320                                         String operator = "AND"; // Future user input
321                                         BooleanClause.Occur clause = BooleanClause.Occur.MUST;
322                                         if (operator.equals("OR")) {
323                                                 clause = BooleanClause.Occur.SHOULD;
324                                         }
325                                         String[] word = title.split(" ");
326                                         for (int j = 0; j < word.length; j++) {
327                                                 critext.add(new TermQuery(input.createTerm(word[j])),
328                                                                 clause);
329                                         }
330                                         query.add(critext, BooleanClause.Occur.MUST);
331                                 }
332                                 List<SimulationContext> context = sprop[i]
333                                                 .getSimulationContexts();
334                                 if (context != null && context.size() > 0) {
335                                         BooleanQuery critext = new BooleanQuery();
336                                         for (Iterator<SimulationContext> j = context.iterator(); j
337                                                         .hasNext();) {
338                                                 SimulationContext seltext = j.next();
339                                                 input = new Term(String.valueOf(seltext.getType()
340                                                                 .getIndex()));
341                                                 critext.add(new TermQuery(input.createTerm(seltext
342                                                                 .getValue())), BooleanClause.Occur.MUST);
343                                         }
344                                         query.add(critext, BooleanClause.Occur.MUST);
345                                 }
346                                 fulquery.add(query, BooleanClause.Occur.SHOULD);
347                         }
348                         if (LOG.isInfoEnabled()) {
349                                 LOG.info("Searching studies by Lucene query \""
350                                                 + fulquery.toString() + "\".");
351                         }
352                         // Creation of the studies filter
353                         BooleanFilter filter = new BooleanFilter();
354                         TermsFilter select = new TermsFilter();
355                         Term mytype = new Term("class");
356                         select.addTerm(mytype.createTerm("Study"));
357                         filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
358
359                         // Creation of the sort criteria
360                         Sort sort = new Sort(new SortField("title", SortField.STRING));
361
362                         // Search
363                         TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
364                                         sort);
365
366                         if (found.totalHits < 1) {
367                                 return result; // No study found
368                         }
369
370                         // Construction of the result list
371                         ScoreDoc[] hits = found.scoreDocs;
372                         for (int i = 0; i < hits.length; i++) {
373                                 result.add(new IndexServiceImpl.ObjectProxy(searcher
374                                                 .doc(hits[i].doc)));
375                         }
376                         searcher.close();
377                 } catch (Exception error) {
378                         LOG.error("Error during Lucene search, reason:", error);
379                 }
380                 return result;
381         }
382
383         /**
384          * {@inheritDoc}
385          * 
386          * @see org.splat.service.SearchService#indexStudy(org.splat.dal.bo.som.Study)
387          */
388         public void indexStudy(final Study study) {
389                 LOG.debug("Index study: id=" + study.getRid() + "; reference="
390                                 + study.getReference());
391                 try {
392                         Study.Properties sprop = new Study.Properties();
393                         List<Proxy> index = selectStudiesWhere(sprop.setReference(study
394                                         .getReference()));
395
396                         if (index.size() != 0) {
397                                 LOG.debug("The given study is already indexed.");
398                                 return; // The given study is already indexed
399                         }
400
401                         IndexService lucin = getIndex();
402                         Scenario[] scenes = study.getScenarii();
403
404                         LOG.debug("Number of study " + study.getReference()
405                                         + " actors: " + study.getActor().size());
406                         lucin.add(study);
407                         if (study.getProgressState() != ProgressState.inWORK) {
408                                 for (int i = 0; i < scenes.length; i++) {
409                                         List<KnowledgeElement> list = scenes[i]
410                                                         .getAllKnowledgeElements();
411                                         for (Iterator<KnowledgeElement> j = list.iterator(); j
412                                                         .hasNext();) {
413                                                 lucin.add(j.next());
414                                                 LOG.debug("Knowlegge added: id="
415                                                                 + j.next().getIndex());
416                                         }
417                                 }
418                         }
419                 } catch (Exception error) {
420                         LOG.error("Unable to index the study '" + study.getIndex()
421                                         + "', reason:", error);
422                 }
423         }
424
425         /**
426          * Get lucene index handler. Create the index if it is not exist.
427          * 
428          * @return IndexService
429          * @throws IOException
430          *             if error when creating a new lucene index
431          */
432         private IndexService getIndex() throws IOException {
433                 IndexService lucin = getIndexService();
434                 if (!lucin.exists()) {
435                         lucin.create(); // Happens when re-indexing all studies
436                 }
437                 return lucin;
438         }
439
440         /**
441          * Get the repositoryService.
442          * 
443          * @return the repositoryService
444          */
445         public RepositoryService getRepositoryService() {
446                 return _repositoryService;
447         }
448
449         /**
450          * Set the repositoryService.
451          * 
452          * @param repositoryService
453          *            the repositoryService to set
454          */
455         public void setRepositoryService(final RepositoryService repositoryService) {
456                 _repositoryService = repositoryService;
457         }
458
459         /**
460          * Get the indexService.
461          * 
462          * @return the indexService
463          */
464         public IndexService getIndexService() {
465                 return _indexService;
466         }
467
468         /**
469          * Set the indexService.
470          * 
471          * @param indexService
472          *            the indexService to set
473          */
474         public void setIndexService(final IndexService indexService) {
475                 _indexService = indexService;
476         }
477
478         /**
479          * Get the studyService.
480          * 
481          * @return the studyService
482          */
483         public StudyService getStudyService() {
484                 return _studyService;
485         }
486
487         /**
488          * Set the studyService.
489          * 
490          * @param studyService
491          *            the studyService to set
492          */
493         public void setStudyService(final StudyService studyService) {
494                 _studyService = studyService;
495         }
496
497         /**
498          * Get the studyDAO.
499          * 
500          * @return the studyDAO
501          */
502         public StudyDAO getStudyDAO() {
503                 return _studyDAO;
504         }
505
506         /**
507          * Set the studyDAO.
508          * 
509          * @param studyDAO
510          *            the studyDAO to set
511          */
512         public void setStudyDAO(final StudyDAO studyDAO) {
513                 _studyDAO = studyDAO;
514         }
515 }