Salome HOME
Refactoring: configuration files are moved into Siman web project.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / som / Database.java
1 package org.splat.som;
2 /**
3  * 
4  * @author    Daniel Brunier-Coulin
5  * @copyright OPEN CASCADE 2012
6  */
7
8 import java.text.SimpleDateFormat;
9 import java.util.ArrayList;
10 import java.util.Date;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Properties;
14 import java.io.File;
15 import java.io.IOException;
16 import java.sql.Connection;
17 import java.sql.DatabaseMetaData;
18 import java.sql.ResultSet;
19 import java.sql.SQLException;
20
21 import org.hibernate.Query;
22 import org.hibernate.Session;
23 import org.hibernate.jdbc.Work;
24 import org.apache.log4j.Logger;
25 import org.apache.lucene.index.Term;
26 import org.apache.lucene.search.BooleanClause;
27 import org.apache.lucene.search.BooleanFilter;
28 import org.apache.lucene.search.BooleanQuery;
29 import org.apache.lucene.search.FilterClause;
30 import org.apache.lucene.search.IndexSearcher;
31 import org.apache.lucene.search.ScoreDoc;
32 import org.apache.lucene.search.Sort;
33 import org.apache.lucene.search.SortField;
34 import org.apache.lucene.search.TermQuery;
35 import org.apache.lucene.search.TermsFilter;
36 import org.apache.lucene.search.TopFieldDocs;
37 import org.apache.lucene.store.Directory;
38 import org.apache.lucene.store.FSDirectory;
39
40 import org.splat.kernel.User;
41 import org.splat.kernel.UserDirectory;
42 import org.splat.kernel.MultiplyDefinedException;
43 import org.splat.kernel.InvalidPropertyException;
44 import org.splat.kernel.MissedPropertyException;
45
46
47 public class Database extends org.splat.kernel.Database {
48
49     private int        uplevel  = 0;          // Level of database upgrade
50     private String     basepath = null;       // Path of the root directory of repository
51
52     private static  Database my = null;       // Singleton instance
53
54     protected class CreateTables extends org.splat.kernel.Database.CreateTables {
55 //  ---------------------------------------------------------------------------         
56       public void execute(Connection connex) throws SQLException
57       {
58         super.execute(connex);
59
60 //      Study Entity
61         String create = "CREATE TABLE `study` (" +
62           "`rid`      int(10)  UNSIGNED NOT NULL," +
63           "`sid`      tinytext NOT NULL," +
64           "`title`    tinytext NOT NULL," +
65           "`state`    enum('inWORK','inDRAFT','inCHECK','APPROVED', 'TEMPLATE') NOT NULL default 'inWORK'," +
66           "`area`     enum('PRIVATE','PUBLIC','REFERENCE')                      NOT NULL default 'PRIVATE'," +
67           "`manager`  int(10)  NOT NULL," +
68           "`version`  tinytext NOT NULL," +
69           "`docount`  int(10)  UNSIGNED NOT NULL," +
70           "`history`  int(10)  UNSIGNED NOT NULL," +
71           "`credate`  date     NOT NULL," +
72           "`lasdate`  date     NOT NULL," +
73           "PRIMARY KEY (`rid`)" +
74           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
75         request.execute(create);
76
77 //      Scenario Entity
78         create = "CREATE TABLE `scenario` (" +
79           "`rid`     int(10)  UNSIGNED NOT NULL," +
80           "`sid`     int(10)  UNSIGNED NOT NULL," +
81           "`owner`   int(10)  NOT NULL," +
82           "`scendex` int(3)   NOT NULL," +
83           "`title`   tinytext NOT NULL," +
84           "`manager` int(10)  NOT NULL," +
85           "`cuser`   int(10)," +
86           "`credate` date     NOT NULL," +
87           "`lasdate` date     NOT NULL," +
88           "PRIMARY KEY (`rid`)" +
89           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
90         request.execute(create);
91
92 //      Document Entity and document tag (Publication)
93         create = "CREATE TABLE `document` (" +
94           "`rid`     int(10)  UNSIGNED NOT NULL," +
95           "`did`     tinytext NOT NULL," +
96           "`type`    int(10)  NOT NULL," +
97           "`step`    int(10)  NOT NULL," +
98           "`state`   enum('inWORK','inDRAFT','inCHECK','APPROVED','EXTERN') NOT NULL default 'inWORK'," +
99           "`name`    tinytext NOT NULL," +
100           "`author`  int(10)  NOT NULL," +
101           "`version` tinytext," +
102           "`countag` int(10)  UNSIGNED NOT NULL," +
103           "`history` int(10)  NOT NULL," +
104           "`myfile`  int(10)  NOT NULL," +
105           "`lasdate` date  NOT NULL," +
106           "PRIMARY KEY (`rid`)" +
107           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
108         request.execute(create);
109         create = "CREATE TABLE `doctag` (" +
110           "`rid`     int(10)  UNSIGNED NOT NULL auto_increment," +
111           "`doc`     int(10)  NOT NULL," +
112           "`owner`   int(10)  NOT NULL," +
113           "`isnew`   char(1)  NOT NULL," + 
114           "PRIMARY KEY (`rid`)" +
115           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
116         request.execute(create);
117 //      Document types
118         create = "CREATE TABLE `doctype` (" +
119           "`rid`    int(10)  UNSIGNED NOT NULL auto_increment," +
120           "`name`   tinytext NOT NULL," +
121           "`state`  enum('inCHECK','APPROVED') NOT NULL default 'inCHECK'," +
122           "`step`   tinytext NOT NULL," +
123           "`result` tinytext," +
124           "PRIMARY KEY (`rid`)" +
125           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
126         request.execute(create);
127 //      Document types dependencies
128         create = "CREATE TABLE `docuse` (" +
129           "`owner` int(10) NOT NULL," +
130           "`rid`   int(10) NOT NULL" +
131           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
132         request.execute(create);
133
134 //      ValidationCycle related object
135         create = "CREATE TABLE `cycle` (" +
136           "`rid`   int(10)  UNSIGNED NOT NULL auto_increment," +
137           "`type`      int(10)  NOT NULL," +
138           "`publisher` int(10)," +
139           "`reviewer`  int(10)," +
140           "`approver`  int(10)," +
141           "`signatory` int(10)," +
142           "PRIMARY KEY (`rid`)" +
143           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
144         request.execute(create);
145
146 //      Timestamp related object
147         create = "CREATE TABLE `stamp` (" +
148           "`rid`     int(10)  UNSIGNED NOT NULL auto_increment," +
149           "`type`    enum('PROMOTION','REVIEW','APPROVAL','ACCEPTANCE','DISTRIBUTION','REFUSAL') NOT NULL," +
150           "`author`  int(10)  NOT NULL," +
151           "`date`    datetime NOT NULL," +
152           "PRIMARY KEY (`rid`)" +
153           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
154         request.execute(create);
155
156 //      KnowledgeElements objects
157         create = "CREATE TABLE `knowelm` (" +
158           "`rid`    int(10)  UNSIGNED NOT NULL auto_increment," +
159           "`type`   int(10)  NOT NULL," +
160           "`owner`  int(10)  NOT NULL," +
161           "`state`  enum('inWORK','inDRAFT','inCHECK','APPROVED') NOT NULL default 'inDRAFT'," +
162           "`title`  tinytext NOT NULL," +
163           "`value`  text     NOT NULL," +
164           "`author` int(10)  NOT NULL," +
165           "`date`   date     NOT NULL," +
166           "PRIMARY KEY (`rid`)" +
167           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
168         request.execute(create);
169 //      KnowledgeElement types
170         create = "CREATE TABLE `knowtype` (" +
171           "`rid`  int(10) UNSIGNED NOT NULL auto_increment," +
172           "`name` tinytext NOT NULL," +
173           "`state`  enum('inWORK','inCHECK','APPROVED') NOT NULL default 'inCHECK'," +
174           "PRIMARY KEY (`rid`)" +
175           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
176         request.execute(create);
177
178 //      SimulationContext objects
179         create = "CREATE TABLE `contelm` (" +
180           "`rid`     int(10) UNSIGNED NOT NULL auto_increment," +
181           "`type`    int(10) NOT NULL," +
182           "`step`    int(10) NOT NULL," +
183           "`state`   enum('inCHECK','APPROVED') NOT NULL default 'inCHECK'," +
184           "`value`   text NOT NULL," +
185           "`counter` int(10)  UNSIGNED NOT NULL," +
186           "PRIMARY KEY (`rid`)" +
187           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
188         request.execute(create);
189 //      SimulationContext types
190         create = "CREATE TABLE `contype` (" +
191           "`rid`  int(10)  UNSIGNED NOT NULL auto_increment," +
192           "`name` tinytext NOT NULL," +
193           "`state`  enum('inCHECK','APPROVED') NOT NULL default 'inCHECK'," +
194           "`step` int(10)  NOT NULL," +
195           "PRIMARY KEY (`rid`)" +
196           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
197         request.execute(create);
198
199 //      Many-to-many association between ProjectElement (Study and Scenario) and SimulationContext
200         create = "CREATE TABLE `projext` (" +
201           "`owner` int(10) NOT NULL," +
202           "`ordex` int(10) NOT NULL," +
203           "`rid`   int(10) NOT NULL" +
204           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
205         request.execute(create);
206         
207 //      File objects
208         create = "CREATE TABLE `file` (" +
209           "`rid`     int(10)  UNSIGNED NOT NULL," +
210           "`format`  tinytext NOT NULL," +
211           "`path`    tinytext NOT NULL," +
212           "`date`    date     NOT NULL," +
213           "PRIMARY KEY (`rid`)" +
214           ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
215         request.execute(create);
216
217 //      Reference objects
218         create = "CREATE TABLE `refid` (" +
219         "`cycle` int(10) NOT NULL," +
220         "`base`  int(10) NOT NULL," +
221         "PRIMARY KEY (`cycle`)" +
222         ") ENGINE=MyISAM DEFAULT CHARSET=latin1";
223         request.execute(create);
224       }
225     }
226     protected class CheckVersion implements Work {
227 //  --------------------------------------------
228       public void execute(Connection connex) throws SQLException
229       {
230         DatabaseMetaData  dbmdata = connex.getMetaData();
231         String            dbname  = "simer";  //TODO: Get the name from meta-data
232         ResultSet         table;
233
234         table   = dbmdata.getTables(dbname, null, "study", null);
235         if (table.next()) return;
236         uplevel = -1;                         // Database not initialized
237       }
238     }
239
240     protected final static Logger   logger = org.splat.kernel.Database.logger;
241     
242 //  ==============================================================================================================================
243 //  Construction
244 //  ==============================================================================================================================
245
246     public static Database getMe () {
247 //  -------------------------------
248       if (my == null) try {
249         my = new Database();
250       }
251       catch (Exception error) {
252         logger.fatal("Could not access the database, reason:", error);
253       }
254       return my;
255     }
256     private Database () {
257 //  -------------------
258       Database.getSession().doWork(new CheckVersion());
259       this.setIDPoolSize(4);                // Average number of generated IDs when creating a study and versioning a document
260     }
261     
262 //  ==============================================================================================================================
263 //  Public member functions
264 //  ==============================================================================================================================
265
266     public boolean isInitialized () {
267 //  -------------------------------
268       return (uplevel >= 0);
269     }
270     
271     public void initialize () throws IOException, SQLException {
272 //  -------------------------      
273       logger.info("Creation of the database.");
274
275 //    Creation of the Lucene index
276       Index.create();                       // May throw IOException if the index repository is improperly configured
277
278 //    Creation of the SIMER SQL tables
279       Session session = Database.getSession();
280       session.doWork(new CreateTables());   // May throw SQLException if the SIMER database does not exist
281       session.flush();
282
283 //    Population of the database with customized data
284       this.populate();
285
286       session.flush();
287       uplevel = 0;                          // The database is now up-to-date
288     }
289     
290 //  ==============================================================================================================================
291 //  Protected member functions
292 //  ==============================================================================================================================
293
294     protected void configure (Properties reprop) {
295 //  --------------------------------------------
296       basepath = reprop.getProperty("repository");
297     }
298
299     protected void populate () {
300 //  --------------------------
301       try {
302 //      Initialization of the schema version
303         this.setSchemaVersion("D0.3");        //TODO: Get the version name from the configuration file
304
305 //      Creation of the default system administrator
306 //TODO: Get the username password from the Hibernate configuration
307         User.Properties uprop = new User.Properties();
308         uprop.setUsername("simer")
309              .setPassword("admin")
310              .setName("Simulation")
311              .setFirstName("Manager")
312              .setDisplayName("label.sysadmin")
313              .addRole("sysadmin")
314              .setMailAddress("noreply@salome-platform.org");
315         uprop.disableCheck();
316         UserDirectory.createUser(uprop);
317       }
318       catch (Exception e) {
319 //      Let's continue, hoping the best...        
320       }
321       ProjectSettings.getMe().initialize();   // Populates the database with all necessary stuff
322     }
323
324 //  ==============================================================================================================================
325 //  Public services
326 //  ==============================================================================================================================
327
328     public static Study createStudy (Study.Properties sprop) throws MissedPropertyException, InvalidPropertyException, MultiplyDefinedException, RuntimeException {
329 //  --------------------------------------------------------            
330           Study  study = new Study(sprop);
331       
332       study.buildReference();
333       Database.getSession().save(study);
334       try {
335         Index lucin = getIndex();
336         lucin.add(study);
337       }
338       catch (IOException error) {
339         logger.error("Unable to index the study '" + study.getIndex() + "', reason:", error);
340 //      Continue and try to index later
341       }
342       return study;
343     }
344
345     public static void indexStudy (Study study) {
346 //  -------------------------------------------
347       try {
348         Study.Properties sprop = new Study.Properties();
349         List<Proxy>      index = Database.selectStudiesWhere(sprop.setReference(study.getReference()));
350
351         if (index.size() != 0) return;     // The given study is already indexed
352
353         Index      lucin  = getIndex();
354         Scenario[] scenes = study.getScenarii();
355
356         lucin.add(study);
357         if (study.getProgressState() != ProgressState.inWORK) for (int i=0; i<scenes.length; i++) {
358           List<KnowledgeElement> list = scenes[i].getAllKnowledgeElements();
359           for (Iterator<KnowledgeElement> j=list.iterator(); j.hasNext(); ) {
360                 lucin.add(j.next());
361           }
362         }
363       }
364       catch (Exception error) {
365         logger.error("Unable to index the study '" + study.getIndex() + "', reason:", error);
366       }
367     }
368
369     public static Index getIndex () throws IOException {
370 //  -------------------------------
371       Index lucin = new Index();
372       if ( !lucin.exists() ) Index.create();     // Happens when re-indexing all studies
373       return lucin;
374     }
375
376     public static File getDownloadDirectory (User user) {
377 //  ---------------------------------------------------
378       StringBuffer  path = new StringBuffer(my.basepath).append("downloads/").append(user.getUsername()).append("/");
379       return  new File(path.toString());
380     }
381
382     public static File getRepositoryIndexDirectory () {
383 //  -------------------------------------------------
384       return new File(my.basepath + "lucin/");
385     }
386
387     public static String getRepositoryVaultPath () {
388 //  --------------------------------------------
389       return (my.basepath + "vault/");
390     }
391
392     public static String getTemplatePath () {
393 //  ---------------------------------------
394       return (my.basepath + "templates/");
395     }
396
397     public static Document selectDocument (int index) {
398 //  -------------------------------------------------
399           StringBuffer  query = new StringBuffer("from Document where rid='").append(index).append("'");          
400           return (Document)Database.getSession().createQuery(query.toString()).uniqueResult();
401     }
402
403     public static Document selectDocument (String refid, String version) {
404 //  --------------------------------------------------------------------
405       StringBuffer  query = new StringBuffer("from Document where did='").append(refid).append("' and version='").append(version).append("'");
406           return (Document)Database.getSession().createQuery(query.toString()).uniqueResult();
407     }
408
409         public static KnowledgeElement selectKnowledgeElement (int index) {
410 //  -----------------------------------------------------------------
411       StringBuffer     query  = new StringBuffer("from KnowledgeElement where rid='").append(index).append("'");
412       KnowledgeElement result = (KnowledgeElement)Database.getSession().createQuery(query.toString()).uniqueResult();
413
414       result.getOwnerScenario().getOwnerStudy().loadWorkflow();
415       return result;
416         }
417         
418         public static List<Proxy> selectKnowledgeElementsWhere (KnowledgeElement.Properties... kprop) {
419 //  ---------------------------------------------------------------------------------------------
420       List<Proxy> result  = new ArrayList<Proxy>();
421       int         hitsize = 20;
422       try {
423
424 //          Creation of the Lucene query
425         File          indir    = Database.getRepositoryIndexDirectory();
426         Directory     index    = FSDirectory.open(indir);               
427         IndexSearcher searcher = new IndexSearcher(index, true);
428         BooleanQuery  fulquery = new BooleanQuery();
429         
430             for (int i=0; i<kprop.length; i++) {
431               BooleanQuery  query = new BooleanQuery();
432               Term          input;                                 // Supposed initialized below at least by the visibility
433         
434           Visibility area = kprop[i].getVisibility();          // Visibility
435           if (area != null) {
436             input = new Term("area");
437             query.add(new TermQuery(input.createTerm(area.toString())), BooleanClause.Occur.MUST);
438           }
439           ProgressState state = kprop[i].getProgressState();   // State
440           if (state != null) {
441                   input = new Term("state");
442             query.add(new TermQuery(input.createTerm(state.toString())), BooleanClause.Occur.MUST);
443           }
444           String refid = kprop[i].getReference();              // Reference
445           if (refid != null) {
446             input = new Term("ref");
447                 query.add(new TermQuery(input.createTerm(refid)), BooleanClause.Occur.MUST);
448           }
449           KnowledgeElementType type = kprop[i].getType();      // Type
450           if (type != null) {
451             input = new Term("type");
452                 query.add(new TermQuery(input.createTerm(type.getName())), BooleanClause.Occur.MUST);
453           }
454           User manager = kprop[i].getAuthor();                 // Author
455           if  (manager != null) {
456             input = new Term("author");
457                 query.add(new TermQuery(input.createTerm(manager.toString())), BooleanClause.Occur.MUST);
458           }
459           User actor = kprop[i].getActor();                    // Contributor, Reviewer or Approver of the owner study
460           if  (actor != null) {
461                 input = new Term("actor");
462                     query.add(new TermQuery(input.createTerm(actor.toString())), BooleanClause.Occur.MUST);
463           }
464           String title = kprop[i].getTitle();                  // Title
465           if (title != null) {
466             input = new Term("contents");
467             BooleanQuery critext  = new BooleanQuery();
468             String       operator = "AND";     // Future user input
469             BooleanClause.Occur        clause = BooleanClause.Occur.MUST;
470             if (operator.equals("OR")) clause = BooleanClause.Occur.SHOULD;
471             String[] word = title.split(" ");
472             for (int j=0; j<word.length; j++) {
473               critext.add(new TermQuery(input.createTerm(word[j])), clause);
474             }
475             query.add(critext, BooleanClause.Occur.MUST);
476           }
477           List<SimulationContext> context = kprop[i].getSimulationContexts();
478           if  (context != null && context.size() > 0) {
479             BooleanQuery critext = new BooleanQuery();
480             for (Iterator<SimulationContext> j=context.iterator(); j.hasNext();) {
481               SimulationContext seltext = j.next();
482               input =  new Term(String.valueOf(seltext.getType().getIndex()));
483               critext.add(new TermQuery(input.createTerm(seltext.getValue())), BooleanClause.Occur.MUST);
484             }
485             query.add(critext, BooleanClause.Occur.MUST);
486           }
487         fulquery.add(query, BooleanClause.Occur.SHOULD);
488             }
489                 if (logger.isInfoEnabled()) {
490             logger.info("Searching knowledges by Lucene query \"" + fulquery.toString() + "\".");
491         }
492 //    Creation of the knowledge filter
493                 BooleanFilter   filter = new BooleanFilter();
494                 TermsFilter     select = new TermsFilter();
495                 Term            mytype = new Term("class");
496                 select.addTerm( mytype.createTerm("KnowledgeElement") );
497                 filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
498
499 //    Creation of the sort criteria
500                 Sort  sort = new Sort(new SortField("title", SortField.STRING));
501
502 //    Search
503         TopFieldDocs found = searcher.search(fulquery, filter, hitsize, sort);
504         
505         if (found.totalHits < 1) return result;   // No study found
506
507 //    Construction of the result list
508         ScoreDoc[] hits = found.scoreDocs;
509             for (int i=0; i<hits.length; i++) {
510                   result.add( new Index.ObjectProxy(searcher.doc(hits[i].doc)) );
511             }
512             searcher.close();             
513       }
514       catch (Exception error) {
515         logger.error("Error during Lucene search, reason:", error);
516       }
517       return result;
518         }
519
520         public static SimulationContext selectSimulationContext (int index) {
521 //  -------------------------------------------------------------------
522       StringBuffer  query = new StringBuffer("from SimulationContext where rid='").append(index).append("'");
523       return (SimulationContext)Database.getSession().createQuery(query.toString()).uniqueResult();
524         }
525
526     public static SimulationContext selectSimulationContext (SimulationContextType celt, String value) {
527 //  --------------------------------------------------------------------------------------------------
528       SimulationContext  result = null;
529       try {
530         SimulationContext.Properties  cprop  = new SimulationContext.Properties();
531         List<SimulationContext>       clist  = selectSimulationContextsWhere(cprop.setType(celt).setValue(value));
532         if (!clist.isEmpty())         result = clist.get(0);   // Supposed being the most used one if many exist
533       }
534       catch (InvalidPropertyException error) {
535         logger.info("Attempt to select a simulation context \"" + celt.getName() + "\" with an invalid value.");
536       }
537       return result;
538     }
539
540         @SuppressWarnings("unchecked")
541         public static List<SimulationContext> selectSimulationContextsWhere (SimulationContext.Properties cprop) {
542 //  --------------------------------------------------------------------------------------------------------
543       StringBuffer           query     = new StringBuffer("from SimulationContext");
544       String                 separator = " where";
545       SimulationContextType  celt      = cprop.getType();
546       String                 value     = cprop.getValue();
547       ProgressState          state     = cprop.getProgressState();
548       String                 order     = "";
549
550           if  (celt != null) {   query     = query.append(separator).append(" type='").append(celt.getIndex()).append("'");
551                                  separator = " and";
552                                  order     = " order by value asc";
553           }
554           if (value != null ) {  query     = query.append(separator).append(" value='").append(value).append("'");
555                              separator = " and";
556           }
557           if (state != null ) {  query     = query.append(separator).append(" state='").append(state).append("'");
558         if (celt == null)    order     = " order by type asc";
559           }
560           query.append(order);
561           return (List<SimulationContext>)Database.getSession().createQuery(query.toString()).list();
562         }
563         
564         public static Study selectStudy (int index) {
565 //  -------------------------------------------
566       StringBuffer  query  = new StringBuffer("from Study where rid='").append(index).append("'");
567       Study         result = (Study)Database.getSession().createQuery(query.toString()).uniqueResult();
568
569       result.loadWorkflow();
570       return result;
571         }
572
573         public static Study selectStudy (String refid) {
574 //  ----------------------------------------------
575       StringBuffer  query  = new StringBuffer("from Study where sid='").append(refid).append("'");                
576       Study         result = (Study)Database.getSession().createQuery(query.toString()).uniqueResult();
577
578       result.loadWorkflow();
579       return result;
580     }
581         
582         public static List<Proxy> selectStudiesWhere (Study.Properties... sprop) {
583 //  ------------------------------------------------------------------------
584       List<Proxy> result  = new ArrayList<Proxy>();
585       int         hitsize = 20;
586       try {
587
588 //    Creation of the Lucene query
589         File          indir    = Database.getRepositoryIndexDirectory();
590         Directory     index    = FSDirectory.open(indir);               
591         IndexSearcher searcher = new IndexSearcher(index, true);
592         BooleanQuery  fulquery = new BooleanQuery();
593         
594             for (int i=0; i<sprop.length; i++) {
595               BooleanQuery  query = new BooleanQuery();
596               Term          input;                                 // Supposed initialized below at least by the visibility
597
598           Visibility area = sprop[i].getVisibility();          // Visibility
599           if (area != null) {
600                 input = new Term("area");
601             query.add(new TermQuery(input.createTerm(area.toString())), BooleanClause.Occur.MUST);
602           }
603           ProgressState state = sprop[i].getProgressState();   // State
604           if (state != null) {
605                 input = new Term("state");
606             if (state == ProgressState.inPROGRESS) {
607                   BooleanQuery cristate = new BooleanQuery();
608                   cristate.add(new TermQuery(input.createTerm("inWORK")),  BooleanClause.Occur.SHOULD);
609                   cristate.add(new TermQuery(input.createTerm("inDRAFT")), BooleanClause.Occur.SHOULD);
610                   cristate.add(new TermQuery(input.createTerm("inCHECK")), BooleanClause.Occur.SHOULD);
611               query.add(cristate, BooleanClause.Occur.MUST);
612             } else {
613               query.add(new TermQuery(input.createTerm(state.toString())), BooleanClause.Occur.MUST);
614             }
615           }
616           String refid = sprop[i].getReference();              // Reference
617           if (refid != null) {
618             input = new Term("ref");
619             query.add(new TermQuery(input.createTerm(refid)), BooleanClause.Occur.MUST);
620           }
621           User manager = sprop[i].getManager();                // Author
622           if  (manager != null) {
623                 input = new Term("author");
624                     query.add(new TermQuery(input.createTerm(manager.toString())), BooleanClause.Occur.MUST);
625           }
626           User actor = sprop[i].getActor();                    // Contributor, Reviewer or Approver
627           if  (actor != null) {
628                 input = new Term("actor");
629                     query.add(new TermQuery(input.createTerm(actor.toString())), BooleanClause.Occur.MUST);
630           }
631           String title = sprop[i].getTitle();                  // Title
632           if (title != null) {
633                 input = new Term("contents");
634                 BooleanQuery critext  = new BooleanQuery();
635                 String       operator = "AND";     // Future user input
636                 BooleanClause.Occur        clause = BooleanClause.Occur.MUST;
637                 if (operator.equals("OR")) clause = BooleanClause.Occur.SHOULD;
638                 String[] word = title.split(" ");
639                 for (int j=0; j<word.length; j++) {
640                   critext.add(new TermQuery(input.createTerm(word[j])), clause);
641                 }
642                 query.add(critext, BooleanClause.Occur.MUST);
643           }
644           List<SimulationContext> context = sprop[i].getSimulationContexts();
645           if  (context != null && context.size() > 0) {
646             BooleanQuery critext = new BooleanQuery();
647                 for (Iterator<SimulationContext> j=context.iterator(); j.hasNext();) {
648               SimulationContext seltext = j.next();
649               input =  new Term(String.valueOf(seltext.getType().getIndex()));
650               critext.add(new TermQuery(input.createTerm(seltext.getValue())), BooleanClause.Occur.MUST);
651             }
652             query.add(critext, BooleanClause.Occur.MUST);
653           }          
654           fulquery.add(query, BooleanClause.Occur.SHOULD);
655             }
656                 if (logger.isInfoEnabled()) {
657             logger.info("Searching studies by Lucene query \"" + fulquery.toString() + "\".");
658         }
659 //    Creation of the studies filter
660                 BooleanFilter   filter = new BooleanFilter();
661                 TermsFilter     select = new TermsFilter();
662                 Term            mytype = new Term("class");
663                 select.addTerm( mytype.createTerm("Study") );
664                 filter.add(new FilterClause(select, BooleanClause.Occur.SHOULD));
665
666 //    Creation of the sort criteria
667                 Sort  sort = new Sort(new SortField("title", SortField.STRING));
668
669 //    Search
670         TopFieldDocs found = searcher.search(fulquery, filter, hitsize, sort);
671         
672         if (found.totalHits < 1) return result;   // No study found
673
674 //    Construction of the result list
675         ScoreDoc[] hits = found.scoreDocs;
676             for (int i=0; i<hits.length; i++) {
677                   result.add( new Index.ObjectProxy(searcher.doc(hits[i].doc)) );
678             }
679             searcher.close();             
680       }
681       catch (Exception error) {
682         logger.error("Error during Lucene search, reason:", error);
683       }
684       return result;
685     }
686
687 //  ==============================================================================================================================
688 //  Protected services
689 //  ==============================================================================================================================
690
691     protected static IDBuilder selectIDBuilder (int cycle) {
692 //  ------------------------------------------------------
693       StringBuffer  buffer  = new StringBuffer("from IDBuilder where cycle='").append(cycle).append("'");
694       String        qstring = buffer.toString();
695       Query         query   = Database.getSession().createQuery(qstring);
696       IDBuilder     result  = (IDBuilder)query.uniqueResult();
697
698       return result;
699     }
700
701     protected static IDBuilder selectIDBuilder (Date date) {
702 //  ------------------------------------------------------
703           SimpleDateFormat year    = new SimpleDateFormat("yyyy");
704           String           cycle   = year.format(date);
705       StringBuffer     buffer  = new StringBuffer("from IDBuilder where cycle='").append(cycle).append("'");
706       String           qstring = buffer.toString();
707       Query            query   = Database.getSession().createQuery(qstring);
708       IDBuilder        result  = (IDBuilder)query.uniqueResult();
709       
710       return result;
711     }
712 }