]> SALOME platform Git repositories - tools/siman.git/blob - Workspace/Siman-Common/src/org/splat/service/SearchServiceImpl.java
Salome HOME
34053560dacc1fe796de3d308da03b26b447cc10
[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.IndexWriter;
20 import org.apache.lucene.index.Term;
21 import org.apache.lucene.search.BooleanClause;
22 import org.apache.lucene.search.BooleanFilter;
23 import org.apache.lucene.search.BooleanQuery;
24 import org.apache.lucene.search.FilterClause;
25 import org.apache.lucene.search.IndexSearcher;
26 import org.apache.lucene.search.ScoreDoc;
27 import org.apache.lucene.search.Sort;
28 import org.apache.lucene.search.SortField;
29 import org.apache.lucene.search.TermQuery;
30 import org.apache.lucene.search.TermsFilter;
31 import org.apache.lucene.search.TopFieldDocs;
32 import org.apache.lucene.store.Directory;
33 import org.apache.lucene.store.FSDirectory;
34 import org.hibernate.Criteria;
35 import org.hibernate.Hibernate;
36 import org.hibernate.criterion.DetachedCriteria;
37 import org.hibernate.criterion.Disjunction;
38 import org.hibernate.criterion.Junction;
39 import org.hibernate.criterion.Order;
40 import org.hibernate.criterion.Restrictions;
41 import org.hibernate.type.Type;
42 import org.splat.dal.bo.kernel.User;
43 import org.splat.dal.bo.som.KnowledgeElement;
44 import org.splat.dal.bo.som.KnowledgeElementType;
45 import org.splat.dal.bo.som.ProgressState;
46 import org.splat.dal.bo.som.Scenario;
47 import org.splat.dal.bo.som.SimulationContext;
48 import org.splat.dal.bo.som.Study;
49 import org.splat.dal.bo.som.Visibility;
50 import org.splat.dal.dao.som.KnowledgeElementDAO;
51 import org.splat.dal.dao.som.StudyDAO;
52 import org.splat.service.dto.ImportedStudyDTO;
53 import org.splat.service.dto.KnowledgeSearchFilterDTO;
54 import org.splat.service.dto.Proxy;
55 import org.splat.service.dto.SearchFilterDTO;
56 import org.splat.service.dto.StudyDTO;
57 import org.splat.service.dto.StudySearchFilterDTO;
58 import org.splat.service.technical.IndexService;
59 import org.splat.service.technical.IndexServiceImpl;
60 import org.splat.service.technical.RepositoryService;
61 import org.splat.util.BeanHelper;
62 import org.springframework.transaction.annotation.Transactional;
63
64 /**
65  * Search service implementation.
66  * 
67  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
68  */
69 public class SearchServiceImpl implements SearchService {
70
71         /**
72          * The service logger.
73          */
74         public final static Logger LOG = Logger
75                         .getLogger(org.splat.service.SearchServiceImpl.class);
76
77         /**
78          * Injected repository service.
79          */
80         private RepositoryService _repositoryService;
81         /**
82          * Injected index service.
83          */
84         private IndexService _indexService;
85         /**
86          * Injected study service.
87          */
88         private StudyService _studyService;
89         /**
90          * Injected study DAO.
91          */
92         private StudyDAO _studyDAO;
93         /**
94          * Injected knowledge element DAO.
95          */
96         private KnowledgeElementDAO _knowledgeElementDAO;
97
98         /**
99          * Get a list of studies which are currently not presented in the lucene index.
100          * 
101          * @return list of ImportedStudy DTO
102          */
103         @Transactional(readOnly = true)
104         public List<ImportedStudyDTO> selectStudies() {
105                 List<ImportedStudyDTO> table = new ArrayList<ImportedStudyDTO>();
106                 Study.Properties sprop = new Study.Properties();
107                 List<Study> dbStudies = getStudyDAO().getAll();
108
109                 for (Study aStudy : dbStudies) {
110                         try {
111                                 sprop.clear();
112                                 if (selectStudiesWhere(
113                                                 sprop.setReference(aStudy.getReference())).size() != 0) {
114                                         // If this study was already indexed and found in the lucene index
115                                         // then skip it to avoid adding to the index it again.
116                                         continue;
117                                 }
118                         } catch (Exception error) {
119                                 continue;
120                         }
121                         // Add the study to the list of studies which are
122                         // currently not presented in the lucene index.
123                         table.add(BeanHelper.copyBean(aStudy, ImportedStudyDTO.class));
124                 }
125                 return table;
126         }
127
128         /**
129          * Refresh lucene index for studies.
130          * 
131          * @param ridlist
132          *            list of studies id's
133          */
134         @Transactional(readOnly = true)
135         @Deprecated
136         public void reindexStudies(final String[] ridlist) {
137                 for (int i = 0; i < ridlist.length; i++) {
138                         long index = Long.valueOf(ridlist[i].trim());
139                         Study study = getStudyService().selectStudy(index);
140                         indexStudy(study);
141                 }
142         }
143
144         /**
145          * {@inheritDoc}
146          * 
147          * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.service.dto.KnowledgeSearchFilterDTO)
148          */
149         public List<Proxy> selectKnowledgeElementsWhere(
150                         final KnowledgeSearchFilterDTO filter) {
151                 List<Proxy> result = new ArrayList<Proxy>();
152
153                 // Search matching all criteria
154                 DetachedCriteria query = DetachedCriteria.forClass(
155                                 KnowledgeElement.class, "kelm");
156                 query.createAlias("kelm.owner", "scen", Criteria.INNER_JOIN)
157                                 .createCriteria("scen.owner", "study", Criteria.INNER_JOIN)
158                                 .add(visibleStudyFilter(filter));
159
160                 // Creation of the query
161                 Junction topJunction = initQuery(filter);
162
163                 addByWordsCriteria(topJunction, filter);
164
165                 List<SimulationContext> context = filter.getSimContexts();
166                 if (context != null && (!context.isEmpty())) {
167                         // Get only studies which have given contexts
168                         query.createAlias("study.contex", "ctx", Criteria.INNER_JOIN);
169                         Junction critctx;
170                         if (filter.isMatchAllContexts()) { // AND
171                                 critctx = Restrictions.conjunction();
172                         } else { // OR
173                                 critctx = Restrictions.disjunction();
174                         }
175                         for (SimulationContext seltext : context) {
176                                 // (simctxType = seltext.getType() AND simctxValue = seltext.getValue())
177                                 critctx.add(Restrictions.and(Restrictions.eq("ctx.value",
178                                                 seltext.getValue()), Restrictions.eq("ctx.type",
179                                                 seltext.getType())));
180
181                         }
182                         topJunction.add(critctx);
183                 }
184
185                 query.add(topJunction);
186                 // Group by study
187                 query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
188                 // Creation of the sort criteria
189                 query.addOrder(Order.asc("title"));
190
191                 if (LOG.isInfoEnabled()) {
192                         LOG.info("Searching knowledge elements: \"" + query.toString());
193                 }
194
195                 // Search
196                 List<KnowledgeElement> found = getKnowledgeElementDAO()
197                                 .getFilteredList(query);
198
199                 // Construction of the result list
200                 for (KnowledgeElement kelm : found) {
201                         result.add(new StudyDTO(kelm.getIndex(), kelm.getReference(), kelm
202                                         .getProgressState(), kelm.getTitle(), kelm.getAuthor()
203                                         .getDisplayName()));
204                 }
205                 return result;
206         }
207
208         /**
209          * Add search criteria for filtering by title contents.
210          * 
211          * @param topJunction
212          *            the search condition to be appended
213          * @param filter
214          *            the criteria
215          */
216         private void addByWordsCriteria(final Junction topJunction,
217                         final SearchFilterDTO filter) {
218                 String title = filter.getWords(); // Title
219                 if (title != null && (!title.isEmpty())) {
220                         // Look for given words in titles
221                         Junction critext;
222                         if (filter.isMatchAllCriteria()) { // AND
223                                 critext = Restrictions.conjunction();
224                         } else { // OR
225                                 critext = Restrictions.disjunction();
226                         }
227
228                         String[] word = title.split(" ");
229                         for (int j = 0; j < word.length; j++) {
230                                 critext.add(Restrictions.like("title", "%" + word[j] + "%"));
231                         }
232                         topJunction.add(critext);
233                 }
234         }
235
236         /**
237          * {@inheritDoc}
238          * 
239          * @see org.splat.service.SearchService#selectKnowledgeElementsWhere(org.splat.dal.bo.som.KnowledgeElement.Properties[])
240          */
241         @Deprecated
242         public List<Proxy> selectKnowledgeElementsWhere(
243                         final KnowledgeElement.Properties... kprop) {
244                 List<Proxy> result = new ArrayList<Proxy>();
245                 int hitsize = 20;
246                 try {
247
248                         // Creation of the Lucene query
249                         File indir = getRepositoryService().getRepositoryIndexDirectory();
250                         Directory index = FSDirectory.open(indir);
251                         IndexSearcher searcher = new IndexSearcher(index, true);
252                         BooleanQuery fulquery = new BooleanQuery();
253
254                         for (int i = 0; i < kprop.length; i++) {
255                                 BooleanQuery query = new BooleanQuery();
256                                 Term input; // Supposed initialized below at least by the visibility
257
258                                 Visibility area = kprop[i].getVisibility(); // Visibility
259                                 if (area != null) {
260                                         input = new Term("area");
261                                         query.add(new TermQuery(input.createTerm(area.toString())),
262                                                         BooleanClause.Occur.MUST);
263                                 }
264                                 ProgressState state = kprop[i].getProgressState(); // State
265                                 if (state != null) {
266                                         input = new Term("state");
267                                         query.add(
268                                                         new TermQuery(input.createTerm(state.toString())),
269                                                         BooleanClause.Occur.MUST);
270                                 }
271                                 String refid = kprop[i].getReference(); // Reference
272                                 if (refid != null) {
273                                         input = new Term("ref");
274                                         query.add(new TermQuery(input.createTerm(refid)),
275                                                         BooleanClause.Occur.MUST);
276                                 }
277                                 KnowledgeElementType type = kprop[i].getType(); // Type
278                                 if (type != null) {
279                                         input = new Term("type");
280                                         query.add(new TermQuery(input.createTerm(type.getName())),
281                                                         BooleanClause.Occur.MUST);
282                                 }
283                                 User manager = kprop[i].getAuthor(); // Author
284                                 if (manager != null) {
285                                         input = new Term("author");
286                                         query.add(new TermQuery(input
287                                                         .createTerm(manager.toString())),
288                                                         BooleanClause.Occur.MUST);
289                                 }
290                                 User actor = kprop[i].getActor(); // Contributor, Reviewer or Approver of the owner study
291                                 if (actor != null) {
292                                         input = new Term("actor");
293                                         query.add(
294                                                         new TermQuery(input.createTerm(actor.toString())),
295                                                         BooleanClause.Occur.MUST);
296                                 }
297                                 String title = kprop[i].getTitle(); // Title
298                                 if (title != null) {
299                                         input = new Term("contents");
300                                         BooleanQuery critext = new BooleanQuery();
301                                         String operator = "AND"; // Future user input
302                                         BooleanClause.Occur clause = BooleanClause.Occur.MUST;
303                                         if (operator.equals("OR")) {
304                                                 clause = BooleanClause.Occur.SHOULD;
305                                         }
306                                         String[] word = title.split(" ");
307                                         for (int j = 0; j < word.length; j++) {
308                                                 critext.add(new TermQuery(input.createTerm(word[j])),
309                                                                 clause);
310                                         }
311                                         query.add(critext, BooleanClause.Occur.MUST);
312                                 }
313                                 List<SimulationContext> context = kprop[i]
314                                                 .getSimulationContexts();
315                                 if (context != null && context.size() > 0) {
316                                         BooleanQuery critext = new BooleanQuery();
317                                         for (Iterator<SimulationContext> j = context.iterator(); j
318                                                         .hasNext();) {
319                                                 SimulationContext seltext = j.next();
320                                                 input = new Term(String.valueOf(seltext.getType()
321                                                                 .getIndex()));
322                                                 critext.add(new TermQuery(input.createTerm(seltext
323                                                                 .getValue())), BooleanClause.Occur.MUST);
324                                         }
325                                         query.add(critext, BooleanClause.Occur.MUST);
326                                 }
327                                 fulquery.add(query, BooleanClause.Occur.SHOULD);
328                         }
329                         if (LOG.isInfoEnabled()) {
330                                 LOG.info("Searching knowledges by Lucene query \""
331                                                 + fulquery.toString());
332                         }
333                         // Creation of the knowledge filter
334                         BooleanFilter filter = new BooleanFilter();
335                         TermsFilter select = new TermsFilter();
336                         Term mytype = new Term("class");
337                         select.addTerm(mytype.createTerm("KnowledgeElement"));
338                         filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
339
340                         // Creation of the sort criteria
341                         Sort sort = new Sort(new SortField("title", SortField.STRING));
342
343                         // Search
344                         TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
345                                         sort);
346
347                         if (found.totalHits < 1) {
348                                 return result; // No study found
349                         }
350
351                         // Construction of the result list
352                         ScoreDoc[] hits = found.scoreDocs;
353                         for (int i = 0; i < hits.length; i++) {
354                                 result.add(new IndexServiceImpl.ObjectProxy(searcher
355                                                 .doc(hits[i].doc)));
356                         }
357                         searcher.close();
358                 } catch (Exception error) {
359                         LOG.error("Error during Lucene search, reason:", error);
360                 }
361                 return result;
362         }
363
364         /**
365          * {@inheritDoc}
366          * 
367          * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.service.dto.StudySearchFilterDTO)
368          */
369         public List<Proxy> selectStudiesWhere(final StudySearchFilterDTO filter) {
370                 List<Proxy> result = new ArrayList<Proxy>();
371
372                 DetachedCriteria query = DetachedCriteria
373                                 .forClass(Study.class, "study").add(visibleStudyFilter(filter));
374
375                 // Creation of the query
376                 Junction topJunction = initQuery(filter);
377
378                 addByWordsCriteria(topJunction, filter);
379
380                 List<SimulationContext> context = filter.getSimContexts();
381                 if (context != null && (!context.isEmpty())) {
382                         // Get only studies which have given contexts
383                         query.createAlias("contex", "ctx", Criteria.INNER_JOIN);
384                         Junction critctx;
385                         if (filter.isMatchAllContexts()) { // AND
386                                 critctx = Restrictions.conjunction();
387                         } else { // OR
388                                 critctx = Restrictions.disjunction();
389                         }
390                         for (SimulationContext seltext : context) {
391                                 // (simctxType = seltext.getType() AND simctxValue = seltext.getValue())
392                                 critctx.add(Restrictions.and(Restrictions.eq("ctx.value",
393                                                 seltext.getValue()), Restrictions.eq("ctx.type",
394                                                 seltext.getType())));
395
396                         }
397                         topJunction.add(critctx);
398                 }
399
400                 query.add(topJunction);
401                 // Group by study
402                 query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
403                 // Creation of the sort criteria
404                 query.addOrder(Order.asc("title"));
405
406                 if (LOG.isInfoEnabled()) {
407                         LOG.info("Searching studies: \"" + query.toString());
408                 }
409
410                 // Search
411                 List<Study> found = getStudyDAO().getFilteredList(query);
412
413                 // Construction of the result list
414                 for (Study std : found) {
415                         result.add(new StudyDTO(std.getIndex(), std.getReference(), std
416                                         .getProgressState(), std.getTitle(), std.getAuthor()
417                                         .getDisplayName()));
418                 }
419                 return result;
420         }
421
422         /**
423          * Initialize query with base criteria.
424          * 
425          * @param filter
426          *            the criteria
427          * @return top junction of the search filter
428          */
429         private Junction initQuery(final StudySearchFilterDTO filter) {
430                 Junction topJunction;
431                 if (filter.isMatchAllCriteria()) { // AND
432                         topJunction = Restrictions.conjunction();
433                 } else { // OR
434                         topJunction = Restrictions.disjunction();
435                 }
436                 if (!StudySearchFilterDTO.ANY_STATE.equals(filter.getState())) {
437                         ProgressState state = ProgressState.valueOf(filter.getState()); // State
438                         if (state != null) {
439                                 topJunction.add(Restrictions.eq("state", state));
440                         }
441                 }
442                 String refid = filter.getReference(); // Reference
443                 if (refid != null && !refid.isEmpty()) {
444                         topJunction.add(Restrictions.eq("sid", refid));
445                 }
446
447                 addDatesCriteria(topJunction, filter);
448
449                 // Filter by study author
450                 long authorId = Long.valueOf(filter.getAuthor());
451                 if (authorId > 0) {
452                         topJunction.add(Restrictions.eq("manager.rid", authorId));
453                 }
454
455                 return topJunction;
456         }
457
458         /**
459          * Initialize query with base criteria.
460          * 
461          * @param filter
462          *            the criteria
463          * @return top junction of the search filter
464          */
465         private Junction initQuery(final KnowledgeSearchFilterDTO filter) {
466                 Junction topJunction;
467                 if (filter.isMatchAllCriteria()) { // AND
468                         topJunction = Restrictions.conjunction();
469                 } else { // OR
470                         topJunction = Restrictions.disjunction();
471                 }
472
473                 // Filter by knowledge type
474                 long ktypeId = Long.valueOf(filter.getKtype());
475                 if (ktypeId > 0) {
476                         topJunction.add(Restrictions.eq("kelm.type.rid", ktypeId));
477                 }
478
479                 String refid = filter.getReference(); // Reference
480                 if (refid != null && !refid.isEmpty()) {
481                         long id = Long.valueOf(refid.replaceAll("^KE(0)*", ""));
482                         if (id > 0) {
483                                 topJunction.add(Restrictions.eq("kelm.rid", id));
484                         }
485                 }
486
487                 addCreationDateCriteria(topJunction, filter, "date");
488
489                 // Filter by knowledge author
490                 long authorId = Long.valueOf(filter.getAuthor());
491                 if (authorId > 0) {
492                         topJunction.add(Restrictions.eq("kelm.author.rid", authorId));
493                 }
494
495                 return topJunction;
496         }
497
498         /**
499          * Filter for visible studies.
500          * 
501          * @param filter
502          *            search criteria
503          * @return search condition for studies to get only visible studies
504          */
505         private Junction visibleStudyFilter(final SearchFilterDTO filter) {
506                 Junction topJunction;
507                 if (filter.isMatchAllCriteria()) { // AND
508                         topJunction = Restrictions.conjunction();
509                 } else { // OR
510                         topJunction = Restrictions.disjunction();
511                 }
512
513                 // Filter by connected user
514                 long actorId = filter.getConnectedUserId(); // Contributor, Reviewer or Approver
515                 if (actorId > 0) {
516                         // User is loggen in - show public studies and studies where he is participating
517                         Disjunction orCrit = Restrictions.disjunction();
518                         topJunction
519                                         .add(orCrit
520                                                         .add(
521                                                                         /* If the user is a validation cycle participant */
522                                                                         Restrictions
523                                                                                         .sqlRestriction(
524                                                                                                         "{alias}.rid in (select vcrel.owner from cycle_rel vcrel inner join cycle vc on vcrel.refer = vc.rid where {alias}.rid = vcrel.owner AND (vc.publisher = ? OR vc.reviewer = ? OR vc.approver = ? OR vc.signatory = ?) group by vcrel.owner)",
525                                                                                                         new Object[] { actorId,
526                                                                                                                         actorId, actorId,
527                                                                                                                         actorId },
528                                                                                                         new Type[] {
529                                                                                                                         Hibernate.LONG,
530                                                                                                                         Hibernate.LONG,
531                                                                                                                         Hibernate.LONG,
532                                                                                                                         Hibernate.LONG }))
533                                                         .add(
534                                                                         /* If the user is contributor */
535                                                                         Restrictions
536                                                                                         .sqlRestriction(
537                                                                                                         "{alias}.rid in (select rel.owner from contributor_rel rel where {alias}.rid = rel.owner AND rel.refer = ?)",
538                                                                                                         actorId, Hibernate.LONG))
539                                                         .add(
540                                                         /* If the user is author */
541                                                         Restrictions.eq("study.manager.rid", actorId)).add(
542                                                                         /* If the study is public */
543                                                                         Restrictions.eq("study.visibility",
544                                                                                         Visibility.PUBLIC)));
545                 } else {
546                         // User is not logged in - show only public studies
547                         topJunction.add(Restrictions.eq("study.visibility",
548                                         Visibility.PUBLIC));
549                 }
550                 return topJunction;
551         }
552
553         /**
554          * Add search criteria by dates to the junction filter condition.
555          * 
556          * @param topJunction
557          *            the junction filter condition
558          * @param filter
559          *            search criteria
560          */
561         private void addDatesCriteria(final Junction topJunction,
562                         final StudySearchFilterDTO filter) {
563                 // Filter by creation date
564                 addCreationDateCriteria(topJunction, filter, "credate");
565                 // Filter by modification date
566                 if (filter.getUpdatedAfter() != null) {
567                         topJunction.add(Restrictions
568                                         .gt("lasdate", filter.getUpdatedAfter()));
569                 }
570                 if (filter.getUpdatedBefore() != null) {
571                         topJunction.add(Restrictions.lt("lasdate", filter
572                                         .getUpdatedBefore()));
573                 }
574
575         }
576
577         /**
578          * Add search criteria by dates to the junction filter condition.
579          * 
580          * @param topJunction
581          *            the junction filter condition
582          * @param filter
583          *            search criteria
584          */
585         private void addCreationDateCriteria(final Junction topJunction,
586                         final SearchFilterDTO filter, final String propName) {
587                 // Filter by creation date
588                 if (filter.getCreatedAfter() != null) {
589                         topJunction.add(Restrictions
590                                         .gt(propName, filter.getCreatedAfter()));
591                 }
592                 if (filter.getCreatedBefore() != null) {
593                         topJunction.add(Restrictions.lt(propName, filter
594                                         .getCreatedBefore()));
595                 }
596         }
597
598         /**
599          * {@inheritDoc}
600          * 
601          * @see org.splat.service.SearchService#selectStudiesWhere(org.splat.dal.bo.som.Study.Properties[])
602          */
603         @Deprecated
604         public List<Proxy> selectStudiesWhere(final Study.Properties... sprop) {
605                 List<Proxy> result = new ArrayList<Proxy>();
606                 int hitsize = 20;
607                 try {
608
609                         // Creation of the Lucene query
610                         File indir = getRepositoryService().getRepositoryIndexDirectory();
611                         Directory index = FSDirectory.open(indir);
612                         IndexSearcher searcher = new IndexSearcher(index, true);
613                         BooleanQuery fulquery = new BooleanQuery();
614
615                         for (int i = 0; i < sprop.length; i++) {
616                                 BooleanQuery query = new BooleanQuery();
617                                 Term input; // Supposed initialized below at least by the visibility
618
619                                 Visibility area = sprop[i].getVisibility(); // Visibility
620                                 if (area != null) {
621                                         input = new Term("area");
622                                         query.add(new TermQuery(input.createTerm(area.toString())),
623                                                         BooleanClause.Occur.MUST);
624                                 }
625                                 ProgressState state = sprop[i].getProgressState(); // State
626                                 if (state != null) {
627                                         input = new Term("state");
628                                         if (state == ProgressState.inPROGRESS) {
629                                                 BooleanQuery cristate = new BooleanQuery();
630                                                 cristate.add(new TermQuery(input.createTerm("inWORK")),
631                                                                 BooleanClause.Occur.SHOULD);
632                                                 cristate.add(
633                                                                 new TermQuery(input.createTerm("inDRAFT")),
634                                                                 BooleanClause.Occur.SHOULD);
635                                                 cristate.add(
636                                                                 new TermQuery(input.createTerm("inCHECK")),
637                                                                 BooleanClause.Occur.SHOULD);
638                                                 query.add(cristate, BooleanClause.Occur.MUST);
639                                         } else {
640                                                 query.add(new TermQuery(input.createTerm(state
641                                                                 .toString())), BooleanClause.Occur.MUST);
642                                         }
643                                 }
644                                 String refid = sprop[i].getReference(); // Reference
645                                 if (refid != null) {
646                                         input = new Term("ref");
647                                         query.add(new TermQuery(input.createTerm(refid)),
648                                                         BooleanClause.Occur.MUST);
649                                 }
650                                 User manager = sprop[i].getManager(); // Author
651                                 if (manager != null) {
652                                         input = new Term("author");
653                                         query.add(new TermQuery(input
654                                                         .createTerm(manager.toString())),
655                                                         BooleanClause.Occur.MUST);
656                                 }
657                                 User actor = sprop[i].getActor(); // Contributor, Reviewer or Approver
658                                 if (actor != null) {
659                                         input = new Term("actor");
660                                         query.add(
661                                                         new TermQuery(input.createTerm(actor.toString())),
662                                                         BooleanClause.Occur.MUST);
663                                 }
664                                 String title = sprop[i].getTitle(); // Title
665                                 if (title != null) {
666                                         input = new Term("contents");
667                                         BooleanQuery critext = new BooleanQuery();
668                                         String operator = "AND"; // Future user input
669                                         BooleanClause.Occur clause = BooleanClause.Occur.MUST;
670                                         if (operator.equals("OR")) {
671                                                 clause = BooleanClause.Occur.SHOULD;
672                                         }
673                                         String[] word = title.split(" ");
674                                         for (int j = 0; j < word.length; j++) {
675                                                 critext.add(new TermQuery(input.createTerm(word[j])),
676                                                                 clause);
677                                         }
678                                         query.add(critext, BooleanClause.Occur.MUST);
679                                 }
680                                 List<SimulationContext> context = sprop[i]
681                                                 .getSimulationContexts();
682                                 if (context != null && context.size() > 0) {
683                                         BooleanQuery critext = new BooleanQuery();
684                                         for (Iterator<SimulationContext> j = context.iterator(); j
685                                                         .hasNext();) {
686                                                 SimulationContext seltext = j.next();
687                                                 input = new Term(String.valueOf(seltext.getType()
688                                                                 .getIndex()));
689                                                 critext.add(new TermQuery(input.createTerm(seltext
690                                                                 .getValue())), BooleanClause.Occur.MUST);
691                                         }
692                                         query.add(critext, BooleanClause.Occur.MUST);
693                                 }
694                                 fulquery.add(query, BooleanClause.Occur.SHOULD);
695                         }
696                         if (LOG.isInfoEnabled()) {
697                                 LOG.info("Searching studies by Lucene query \""
698                                                 + fulquery.toString());
699                         }
700                         // Creation of the studies filter
701                         BooleanFilter filter = new BooleanFilter();
702                         TermsFilter select = new TermsFilter();
703                         Term mytype = new Term("class");
704                         select.addTerm(mytype.createTerm("Study"));
705                         filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
706
707                         // Creation of the sort criteria
708                         Sort sort = new Sort(new SortField("title", SortField.STRING));
709
710                         // Search
711                         TopFieldDocs found = searcher.search(fulquery, filter, hitsize,
712                                         sort);
713
714                         if (found.totalHits < 1) {
715                                 return result; // No study found
716                         }
717
718                         // Construction of the result list
719                         ScoreDoc[] hits = found.scoreDocs;
720                         for (int i = 0; i < hits.length; i++) {
721                                 result.add(new IndexServiceImpl.ObjectProxy(searcher
722                                                 .doc(hits[i].doc)));
723                         }
724                         searcher.close();
725                 } catch (Exception error) {
726                         LOG.error("Error during Lucene search, reason:", error);
727                 }
728                 return result;
729         }
730
731         /**
732          * {@inheritDoc}
733          * 
734          * @see org.splat.service.SearchService#indexStudy(org.splat.dal.bo.som.Study)
735          */
736         @Deprecated
737         public void indexStudy(final Study study) {
738                 LOG.debug("Index study: id=" + study.getRid() + "; reference="
739                                 + study.getReference());
740                 try {
741                         Study.Properties sprop = new Study.Properties();
742                         List<Proxy> index = selectStudiesWhere(sprop.setReference(study
743                                         .getReference()));
744
745                         if (index.size() != 0) {
746                                 LOG.debug("The given study is already indexed.");
747                                 return; // The given study is already indexed
748                         }
749
750                         IndexService lucin = getIndex();
751                         Scenario[] scenes = study.getScenarii();
752
753                         LOG.debug("Number of study " + study.getReference() + " actors: "
754                                         + study.getActor().size());
755                         lucin.add(study);
756                         if (study.getProgressState() != ProgressState.inWORK) {
757                                 for (int i = 0; i < scenes.length; i++) {
758                                         List<KnowledgeElement> list = scenes[i]
759                                                         .getAllKnowledgeElements();
760                                         for (Iterator<KnowledgeElement> j = list.iterator(); j
761                                                         .hasNext();) {
762                                                 lucin.add(j.next());
763                                                 LOG.debug("Knowlegge added: id=" + j.next().getIndex());
764                                         }
765                                 }
766                         }
767                 } catch (Exception error) {
768                         LOG.error("Unable to index the study '" + study.getIndex()
769                                         + "', reason:", error);
770                 }
771         }
772
773         /**
774          * Get lucene index handler. Create the index if it is not exist.
775          * 
776          * @return IndexService
777          * @throws IOException
778          *             if error when creating a new lucene index
779          */
780         private IndexService getIndex() throws IOException {
781                 IndexService lucin = getIndexService();
782                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
783                                 .getRepositoryIndexDirectory()))) {
784                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
785                                         .getRepositoryIndexDirectory()));
786                 }
787                 if (!lucin.exists()) {
788                         lucin.create(); // Happens when re-indexing all studies
789                 }
790                 return lucin;
791         }
792
793         /**
794          * Get the repositoryService.
795          * 
796          * @return the repositoryService
797          */
798         public RepositoryService getRepositoryService() {
799                 return _repositoryService;
800         }
801
802         /**
803          * Set the repositoryService.
804          * 
805          * @param repositoryService
806          *            the repositoryService to set
807          */
808         public void setRepositoryService(final RepositoryService repositoryService) {
809                 _repositoryService = repositoryService;
810         }
811
812         /**
813          * Get the indexService.
814          * 
815          * @return the indexService
816          */
817         public IndexService getIndexService() {
818                 return _indexService;
819         }
820
821         /**
822          * Set the indexService.
823          * 
824          * @param indexService
825          *            the indexService to set
826          */
827         public void setIndexService(final IndexService indexService) {
828                 _indexService = indexService;
829         }
830
831         /**
832          * Get the studyService.
833          * 
834          * @return the studyService
835          */
836         public StudyService getStudyService() {
837                 return _studyService;
838         }
839
840         /**
841          * Set the studyService.
842          * 
843          * @param studyService
844          *            the studyService to set
845          */
846         public void setStudyService(final StudyService studyService) {
847                 _studyService = studyService;
848         }
849
850         /**
851          * Get the studyDAO.
852          * 
853          * @return the studyDAO
854          */
855         public StudyDAO getStudyDAO() {
856                 return _studyDAO;
857         }
858
859         /**
860          * Set the studyDAO.
861          * 
862          * @param studyDAO
863          *            the studyDAO to set
864          */
865         public void setStudyDAO(final StudyDAO studyDAO) {
866                 _studyDAO = studyDAO;
867         }
868
869         /**
870          * Get the knowledgeElementDAO.
871          * 
872          * @return the knowledgeElementDAO
873          */
874         public KnowledgeElementDAO getKnowledgeElementDAO() {
875                 return _knowledgeElementDAO;
876         }
877
878         /**
879          * Set the knowledgeElementDAO.
880          * 
881          * @param knowledgeElementDAO
882          *            the knowledgeElementDAO to set
883          */
884         public void setKnowledgeElementDAO(
885                         final KnowledgeElementDAO knowledgeElementDAO) {
886                 _knowledgeElementDAO = knowledgeElementDAO;
887         }
888 }