Salome HOME
d1960d2c252b4d61a4a54fc2b94c01df1980cbc6
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / technical / IndexServiceImpl.java
1 package org.splat.service.technical;
2
3 /**
4  * 
5  * @author    Daniel Brunier-Coulin
6  * @copyright OPEN CASCADE 2012-2015
7  */
8
9 import java.io.File;
10 import java.io.IOException;
11 import java.io.Serializable;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Set;
15
16 import org.apache.log4j.Logger;
17 import org.apache.lucene.analysis.standard.StandardAnalyzer;
18 import org.apache.lucene.document.Field;
19 import org.apache.lucene.index.CorruptIndexException;
20 import org.apache.lucene.index.IndexReader;
21 import org.apache.lucene.index.IndexWriter;
22 import org.apache.lucene.index.Term;
23 import org.apache.lucene.store.Directory;
24 import org.apache.lucene.store.FSDirectory;
25 import org.apache.lucene.store.LockObtainFailedException;
26 import org.apache.lucene.util.Version;
27 import org.splat.dal.bo.kernel.User;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.ProgressState;
30 import org.splat.dal.bo.som.Scenario;
31 import org.splat.dal.bo.som.SimulationContext;
32 import org.splat.dal.bo.som.Study;
33 import org.splat.service.ProjectElementService;
34 import org.splat.service.dto.Proxy;
35 import org.splat.som.Step;
36
37 /**
38  * Implementation of the service for work with Lucen index.
39  */
40 public class IndexServiceImpl implements IndexService {
41
42         /**
43          * The logger for this service.
44          */
45         private static final Logger LOG = Logger.getLogger(IndexServiceImpl.class);
46
47         private final static String PROP_INDEX = "index";
48         private final static String PROP_REF = "ref";
49         private final static String PROP_STATE = "state";
50         private final static String PROP_AUTHOR = "author";
51         private final static String PROP_TITLE = "title";
52
53         private transient Directory _index;
54         private transient org.apache.lucene.document.Document _body;
55         private ProjectElementService _projectElementService;
56         private RepositoryService _repositoryService;
57
58         protected static StandardAnalyzer analyzer = new StandardAnalyzer(
59                         Version.LUCENE_29);
60
61         private class Entry extends IndexWriter {
62                 private transient final org.apache.lucene.document.Document _entry;
63
64                 private Entry(final Study study) throws CorruptIndexException,
65                                 LockObtainFailedException, IOException {
66                         super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
67
68                         // Addition of mandatory fields
69                         _entry = new org.apache.lucene.document.Document();
70                         Field field;
71                         field = _body.getField(PROP_INDEX);
72                         field.setValue(String.valueOf(study.getIndex()));
73                         _entry.add(field);
74                         field = _body.getField("class");
75                         field.setValue("Study");
76                         _entry.add(field);
77                         field = _body.getField("type");
78                         field.setValue(""); // Reserved for configurable Study type
79                         _entry.add(field);
80                         field = _body.getField(PROP_REF);
81                         field.setValue(study.getReference());
82                         _entry.add(field);
83                         field = _body.getField("area");
84                         field.setValue(study.getVisibility().toString());
85                         _entry.add(field);
86                         field = _body.getField(PROP_STATE);
87                         field.setValue(study.getProgressState().toString());
88                         _entry.add(field);
89                         field = _body.getField(PROP_AUTHOR);
90                         field.setValue(study.getAuthor().toString());
91                         _entry.add(field);
92                         field = _body.getField(PROP_TITLE);
93                         field.setValue(study.getTitle());
94                         _entry.add(field);
95                         field = _body.getField("contents");
96                         field.setValue(study.getTitle());
97                         _entry.add(field);
98
99                         // Addition of optional fields
100                         setActorsOf(study);
101                         setContextAt(getProjectElementService().getSteps(study));
102                 }
103
104                 private Entry(final KnowledgeElement kelm)
105                                 throws CorruptIndexException, LockObtainFailedException,
106                                 IOException {
107                         super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
108
109                         // Addition of mandatory fields
110                         _entry = new org.apache.lucene.document.Document();
111                         Field field;
112                         field = _body.getField(PROP_INDEX);
113                         field.setValue(String.valueOf(kelm.getIndex()));
114                         _entry.add(field);
115                         field = _body.getField("class");
116                         field.setValue("KnowledgeElement");
117                         _entry.add(field);
118                         field = _body.getField("type");
119                         field.setValue(kelm.getType().getName());
120                         _entry.add(field);
121                         field = _body.getField(PROP_REF);
122                         field.setValue(kelm.getReference());
123                         _entry.add(field);
124                         field = _body.getField("area");
125                         field.setValue(kelm.getVisibility().toString());
126                         _entry.add(field);
127                         field = _body.getField(PROP_STATE);
128                         field.setValue(kelm.getProgressState().toString());
129                         _entry.add(field);
130                         field = _body.getField(PROP_AUTHOR);
131                         field.setValue(kelm.getAuthor().toString());
132                         _entry.add(field);
133                         field = _body.getField(PROP_TITLE);
134                         field.setValue(kelm.getTitle());
135                         _entry.add(field);
136                         field = _body.getField("contents");
137                         field.setValue(kelm.getTitle());
138                         _entry.add(field);
139
140                         // TODO: Addition of optional fields
141                         Scenario scene = kelm.getOwnerScenario();
142                         Study study = scene.getOwnerStudy();
143                         setActorsOf(study); // For restricting the visibility of knowledges attached to private studies
144                         setContextAt(getProjectElementService().getSteps(study));
145                         setContextAt(getProjectElementService().getSteps(scene));
146                 }
147
148                 private void add() throws CorruptIndexException, IOException {
149                         try {
150                                 addDocument(_entry);
151                                 // Save the new entry
152                                 optimize(); // Should be called before committing the index
153                                 close(); // Commits the index
154                         } finally {
155                                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
156                                                 .getRepositoryIndexDirectory()))) {
157                                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
158                                                         .getRepositoryIndexDirectory()));
159                                 }
160                         }
161                 }
162
163                 private void update() throws CorruptIndexException, IOException {
164                         try {
165                                 String value = _entry.getField(PROP_REF).stringValue(); // Only field with unique value
166                                 Term term = new Term(PROP_REF).createTerm(value);
167                                 updateDocument(term, _entry);
168                                 // Save the updated entry
169                                 optimize(); // Should be called before committing the index
170                                 close(); // Commits the index
171                         } finally {
172                                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
173                                                 .getRepositoryIndexDirectory()))) {
174                                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
175                                                         .getRepositoryIndexDirectory()));
176                                 }
177                         }
178                 }
179
180                 private void setContextAt(final Step[] step) {
181                         for (int i = 0; i < step.length; i++) {
182                                 List<SimulationContext> contexts = step[i]
183                                                 .getAllSimulationContexts();
184                                 for (Iterator<SimulationContext> j = contexts.iterator(); j
185                                                 .hasNext();) {
186                                         SimulationContext context = j.next();
187                                         String type = String.valueOf(context.getType().getIndex());
188                                         String value = context.getValue();
189                                         _entry.add(new Field(type, value, Field.Store.NO,
190                                                         Field.Index.NOT_ANALYZED));
191                                 }
192                         }
193                 }
194
195                 private void setActorsOf(final Study study) {
196                         // RKV: This set is always not null. Let's assume that it must be initialized before reindexing: Set<User> actors =
197                         // study.getActors();
198                         Set<User> actors = study.getActor(); // RKV
199                         if (LOG.isDebugEnabled()) {
200                                 LOG.debug("Study " + study.getReference()
201                                                 + " actors number to be added to the lucen index: "
202                                                 + actors.size());
203                         }
204                         for (Iterator<User> i = actors.iterator(); i.hasNext();) {
205                                 String value = i.next().toString();
206                                 _entry.add(new Field("actor", value, Field.Store.NO,
207                                                 Field.Index.NOT_ANALYZED));
208                                 if (LOG.isDebugEnabled()) {
209                                         LOG.debug("    actor added to the lucen index: " + value);
210                                 }
211                         }
212                 }
213         }
214
215         public static class ObjectProxy implements Proxy, Serializable {
216                 private transient final Long _rid;
217                 private transient final String _sid;
218                 private transient final ProgressState _state;
219                 private transient final String _title;
220                 private transient String _type;
221                 private transient final String _name;
222                 private static final long serialVersionUID = -4386494192709562221L;
223
224                 public ObjectProxy(final org.apache.lucene.document.Document ludoc) {
225                         _rid = Long.valueOf(ludoc.get(PROP_INDEX));
226                         _sid = ludoc.get(PROP_REF);
227                         _state = ProgressState.valueOf(ludoc.get(PROP_STATE));
228                         _title = ludoc.get(PROP_TITLE);
229                         _name = ludoc.get(PROP_AUTHOR);
230                 }
231
232                 public String getAuthorName() {
233                         return _name;
234                 }
235
236                 public Long getIndex() {
237                         return _rid;
238                 }
239
240                 public ProgressState getProgressState() {
241                         return _state;
242                 }
243
244                 public String getReference() {
245                         return _sid;
246                 }
247
248                 public String getTitle() {
249                         return _title;
250                 }
251
252                 public String getType() {
253                         return _type;
254                 }
255         }
256
257         // ==============================================================================================================================
258         // Construction
259         // ==============================================================================================================================
260
261         public void configure() throws IOException {
262                 File indir = getRepositoryService().getRepositoryIndexDirectory();
263                 if (_index != null) {
264                         try {
265                                 _index.close();
266                         } finally {
267                                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
268                                                 .getRepositoryIndexDirectory()))) {
269                                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
270                                                         .getRepositoryIndexDirectory()));
271                                 }
272                         }
273                 }
274                 _index = FSDirectory.open(indir);
275                 _body = new org.apache.lucene.document.Document();
276                 _body.add(new Field(PROP_INDEX, "", Field.Store.YES,
277                                 Field.Index.NOT_ANALYZED));
278                 _body.add(new Field("class", "", Field.Store.NO,
279                                 Field.Index.NOT_ANALYZED));
280                 _body.add(new Field("type", "", Field.Store.YES,
281                                 Field.Index.NOT_ANALYZED));
282                 _body.add(new Field(PROP_REF, "", Field.Store.YES,
283                                 Field.Index.NOT_ANALYZED));
284                 _body.add(new Field("area", "", Field.Store.NO,
285                                 Field.Index.NOT_ANALYZED));
286                 _body.add(new Field(PROP_STATE, "", Field.Store.YES,
287                                 Field.Index.NOT_ANALYZED));
288                 _body.add(new Field(PROP_AUTHOR, "", Field.Store.YES,
289                                 Field.Index.NOT_ANALYZED));
290                 _body.add(new Field(PROP_TITLE, "", Field.Store.YES,
291                                 Field.Index.NOT_ANALYZED));
292                 _body.add(new Field("contents", "", Field.Store.NO,
293                                 Field.Index.ANALYZED));
294                 if (!this.exists()) {
295                         this.create(); // Happens when re-indexing all studies
296                 }
297         }
298
299         public void create() throws IOException {
300                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
301                                 .getRepositoryIndexDirectory()))) {
302                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
303                                         .getRepositoryIndexDirectory()));
304                 }
305                 Directory index = FSDirectory.open(getRepositoryService()
306                                 .getRepositoryIndexDirectory());
307                 if (IndexWriter.isLocked(index)) {
308                         IndexWriter.unlock(index);
309                 }
310                 IndexWriter writer = null;
311                 try {
312                         writer = new IndexWriter(index, analyzer, true,
313                                         IndexWriter.MaxFieldLength.UNLIMITED);
314                 } finally {
315                         if (writer != null) {
316                                 try {
317                                         writer.optimize();
318                                         writer.close(); // ==== Creates an empty index
319                                 } finally {
320                                         if (IndexWriter.isLocked(index)) {
321                                                 IndexWriter.unlock(index);
322                                         }
323                                 }
324                         }
325                 }
326         }
327
328         // ==============================================================================================================================
329         // Member functions
330         // ==============================================================================================================================
331
332         public void add(final Study study) throws IOException {
333                 IndexServiceImpl.Entry entry = new Entry(study);
334                 entry.add();
335                 if (LOG.isInfoEnabled()) {
336                         LOG.info("Study \"" + study.getIndex() + "\" indexed.");
337                 }
338         }
339
340         public void add(final KnowledgeElement kelm) throws IOException {
341                 IndexServiceImpl.Entry entry = new Entry(kelm);
342                 entry.add();
343                 if (LOG.isInfoEnabled()) {
344                         LOG.info("Knowledge \"" + kelm.getIndex() + "\" indexed.");
345                 }
346         }
347
348         public boolean exists() {
349                 boolean res = false;
350                 try {
351                         res = IndexReader.indexExists(_index);
352                 } catch (IOException error) {
353                         LOG.error(error.getMessage(), error);
354                 }
355                 return res;
356         }
357
358         public void update(final Study study) throws IOException {
359                 IndexServiceImpl.Entry entry = new Entry(study);
360                 entry.update();
361                 if (LOG.isInfoEnabled()) {
362                         LOG.info("Study \"" + study.getIndex() + "\" re-indexed.");
363                 }
364         }
365
366         public void update(final KnowledgeElement kelm) throws IOException {
367                 IndexServiceImpl.Entry entry = new Entry(kelm);
368                 entry.update();
369                 if (LOG.isInfoEnabled()) {
370                         LOG.info("Knowledge \"" + kelm.getIndex() + "\" re-indexed.");
371                 }
372         }
373
374         /**
375          * Get the projectElementService.
376          * 
377          * @return the projectElementService
378          */
379         public ProjectElementService getProjectElementService() {
380                 return _projectElementService;
381         }
382
383         /**
384          * Set the projectElementService.
385          * 
386          * @param projectElementService
387          *            the projectElementService to set
388          */
389         public void setProjectElementService(
390                         final ProjectElementService projectElementService) {
391                 _projectElementService = projectElementService;
392         }
393
394         /**
395          * Get the repositoryService.
396          * 
397          * @return the repositoryService
398          */
399         public RepositoryService getRepositoryService() {
400                 return _repositoryService;
401         }
402
403         /**
404          * Set the repositoryService.
405          * 
406          * @param repositoryService
407          *            the repositoryService to set
408          */
409         public void setRepositoryService(final RepositoryService repositoryService) {
410                 _repositoryService = repositoryService;
411         }
412 }