Salome HOME
Modifications done to respect PMD rules. Versioning a document is fixed. Validation...
[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
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
46         .getLogger(IndexServiceImpl.class);
47
48         private final static String PROP_INDEX  = "index";
49         private final static String PROP_REF    = "ref";
50         private final static String PROP_STATE  = "state";
51         private final static String PROP_AUTHOR = "author";
52         private final static String PROP_TITLE  = "title";
53         
54         private transient Directory _index;
55         private transient org.apache.lucene.document.Document _body;
56         private ProjectElementService _projectElementService;
57         private RepositoryService _repositoryService;
58
59         protected static StandardAnalyzer analyzer = new StandardAnalyzer(
60                         Version.LUCENE_29);
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) throws CorruptIndexException,
105                                 LockObtainFailedException, IOException {
106                         super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
107
108                         // Addition of mandatory fields
109                         _entry = new org.apache.lucene.document.Document();
110                         Field field;
111                         field = _body.getField(PROP_INDEX);
112                         field.setValue(String.valueOf(kelm.getIndex()));
113                         _entry.add(field);
114                         field = _body.getField("class");
115                         field.setValue("KnowledgeElement");
116                         _entry.add(field);
117                         field = _body.getField("type");
118                         field.setValue(kelm.getType().getName());
119                         _entry.add(field);
120                         field = _body.getField(PROP_REF);
121                         field.setValue(kelm.getReference());
122                         _entry.add(field);
123                         field = _body.getField("area");
124                         field.setValue(kelm.getVisibility().toString());
125                         _entry.add(field);
126                         field = _body.getField(PROP_STATE);
127                         field.setValue(kelm.getProgressState().toString());
128                         _entry.add(field);
129                         field = _body.getField(PROP_AUTHOR);
130                         field.setValue(kelm.getAuthor().toString());
131                         _entry.add(field);
132                         field = _body.getField(PROP_TITLE);
133                         field.setValue(kelm.getTitle());
134                         _entry.add(field);
135                         field = _body.getField("contents");
136                         field.setValue(kelm.getTitle());
137                         _entry.add(field);
138
139                         // TODO: Addition of optional fields
140                         Scenario scene = kelm.getOwnerScenario();
141                         Study study = scene.getOwnerStudy();
142                         setActorsOf(study); // For restricting the visibility of knowledges attached to private studies
143                         setContextAt(getProjectElementService().getSteps(study));
144                         setContextAt(getProjectElementService().getSteps(scene));
145                 }
146
147                 private void add() throws CorruptIndexException, IOException {
148                         addDocument(_entry);
149                         // Save the new entry
150                         optimize(); // Should be called before committing the index
151                         close(); // Commits the index
152                 }
153
154                 private void update() throws CorruptIndexException, IOException {
155                         String value = _entry.getField(PROP_REF).stringValue(); // Only field with unique value
156                         Term term = new Term(PROP_REF).createTerm(value);
157                         updateDocument(term, _entry);
158                         // Save the updated entry
159                         optimize(); // Should be called before committing the index
160                         close(); // Commits the index
161                 }
162
163                 private void setContextAt(final Step[] step) {
164                         for (int i = 0; i < step.length; i++) {
165                                 List<SimulationContext> contexts = step[i]
166                                                 .getAllSimulationContexts();
167                                 for (Iterator<SimulationContext> j = contexts.iterator(); j
168                                                 .hasNext();) {
169                                         SimulationContext context = j.next();
170                                         String type = String.valueOf(context.getType().getIndex());
171                                         String value = context.getValue();
172                                         _entry.add(new Field(type, value, Field.Store.NO,
173                                                         Field.Index.NOT_ANALYZED));
174                                 }
175                         }
176                 }
177
178                 private void setActorsOf(final Study study) {
179                         // RKV: This set is always not null. Let's assume that it must be initialized before reindexing: Set<User> actors =
180                         // study.getActors();
181                         Set<User> actors = study.getActor(); // RKV
182                         if (LOG.isDebugEnabled()) {
183                                 LOG.debug("Study " + study.getReference()
184                                                 + " actors number to be added to the lucen index: "
185                                                 + actors.size());
186                         }
187                         for (Iterator<User> i = actors.iterator(); i.hasNext();) {
188                                 String value = i.next().toString();
189                                 _entry.add(new Field("actor", value, Field.Store.NO,
190                                                 Field.Index.NOT_ANALYZED));
191                                 if (LOG.isDebugEnabled()) {
192                                         LOG.debug("    actor added to the lucen index: " + value);
193                                 }
194                         }
195                 }
196         }
197
198         public static class ObjectProxy implements Proxy, Serializable {
199                 private transient final Long _rid;
200                 private transient final String _sid;
201                 private transient final ProgressState _state;
202                 private transient final String _title;
203                 private transient String _type;
204                 private transient final String _name;
205                 private static final long serialVersionUID = -4386494192709562221L;
206
207                 public ObjectProxy(final org.apache.lucene.document.Document ludoc) {
208                         _rid = Long.valueOf(ludoc.get(PROP_INDEX));
209                         _sid = ludoc.get(PROP_REF);
210                         _state = ProgressState.valueOf(ludoc.get(PROP_STATE));
211                         _title = ludoc.get(PROP_TITLE);
212                         _name = ludoc.get(PROP_AUTHOR);
213                 }
214
215                 public String getAuthorName() {
216                         return _name;
217                 }
218
219                 public Long getIndex() {
220                         return _rid;
221                 }
222
223                 public ProgressState getProgressState() {
224                         return _state;
225                 }
226
227                 public String getReference() {
228                         return _sid;
229                 }
230
231                 public String getTitle() {
232                         return _title;
233                 }
234
235                 public String getType() {
236                         return _type;
237                 }
238         }
239
240         // ==============================================================================================================================
241         // Construction
242         // ==============================================================================================================================
243
244         public void configure() throws IOException {
245                 File indir = getRepositoryService().getRepositoryIndexDirectory();
246                 _index = FSDirectory.open(indir);
247                 _body = new org.apache.lucene.document.Document();
248                 _body.add(new Field(PROP_INDEX, "", Field.Store.YES,
249                                 Field.Index.NOT_ANALYZED));
250                 _body.add(new Field("class", "", Field.Store.NO,
251                                 Field.Index.NOT_ANALYZED));
252                 _body.add(new Field("type", "", Field.Store.YES,
253                                 Field.Index.NOT_ANALYZED));
254                 _body
255                                 .add(new Field(PROP_REF, "", Field.Store.YES,
256                                                 Field.Index.NOT_ANALYZED));
257                 _body
258                                 .add(new Field("area", "", Field.Store.NO,
259                                                 Field.Index.NOT_ANALYZED));
260                 _body.add(new Field(PROP_STATE, "", Field.Store.YES,
261                                 Field.Index.NOT_ANALYZED));
262                 _body.add(new Field(PROP_AUTHOR, "", Field.Store.YES,
263                                 Field.Index.NOT_ANALYZED));
264                 _body.add(new Field(PROP_TITLE, "", Field.Store.YES,
265                                 Field.Index.NOT_ANALYZED));
266                 _body
267                                 .add(new Field("contents", "", Field.Store.NO,
268                                                 Field.Index.ANALYZED));
269                 if (!this.exists()) {
270                         this.create(); // Happens when re-indexing all studies
271                 }
272         }
273
274         public void create() throws IOException {
275                 Directory index = FSDirectory.open(getRepositoryService()
276                                 .getRepositoryIndexDirectory());
277                 IndexWriter writer = new IndexWriter(index, analyzer, true,
278                                 IndexWriter.MaxFieldLength.UNLIMITED);
279                 writer.close(); // ==== Creates an empty index
280         }
281
282         // ==============================================================================================================================
283         // Member functions
284         // ==============================================================================================================================
285
286         public void add(final Study study) throws IOException {
287                 IndexServiceImpl.Entry entry = new Entry(study);
288                 entry.add();
289                 if (LOG.isInfoEnabled()) {
290                         LOG.info("Study \"" + study.getIndex() + "\" indexed.");
291                 }
292         }
293
294         public void add(final KnowledgeElement kelm) throws IOException {
295                 IndexServiceImpl.Entry entry = new Entry(kelm);
296                 entry.add();
297                 if (LOG.isInfoEnabled()) {
298                         LOG.info("Knowledge \"" + kelm.getIndex() + "\" indexed.");
299                 }
300         }
301
302         public boolean exists() {
303                 boolean res = false;
304                 try {
305                         res = IndexReader.indexExists(_index);
306                 } catch (IOException error) {
307                         LOG.error(error.getMessage(), error);
308                 }
309                 return res;
310         }
311
312         public void update(final Study study) throws IOException {
313                 IndexServiceImpl.Entry entry = new Entry(study);
314                 entry.update();
315                 if (LOG.isInfoEnabled()) {
316                         LOG.info("Study \"" + study.getIndex() + "\" re-indexed.");
317                 }
318         }
319
320         public void update(final KnowledgeElement kelm) throws IOException {
321                 IndexServiceImpl.Entry entry = new Entry(kelm);
322                 entry.update();
323                 if (LOG.isInfoEnabled()) {
324                         LOG.info("Knowledge \"" + kelm.getIndex() + "\" re-indexed.");
325                 }
326         }
327
328         /**
329          * Get the projectElementService.
330          * 
331          * @return the projectElementService
332          */
333         public ProjectElementService getProjectElementService() {
334                 return _projectElementService;
335         }
336
337         /**
338          * Set the projectElementService.
339          * 
340          * @param projectElementService
341          *            the projectElementService to set
342          */
343         public void setProjectElementService(
344                         final ProjectElementService projectElementService) {
345                 _projectElementService = projectElementService;
346         }
347
348         /**
349          * Get the repositoryService.
350          * 
351          * @return the repositoryService
352          */
353         public RepositoryService getRepositoryService() {
354                 return _repositoryService;
355         }
356
357         /**
358          * Set the repositoryService.
359          * 
360          * @param repositoryService
361          *            the repositoryService to set
362          */
363         public void setRepositoryService(final RepositoryService repositoryService) {
364                 _repositoryService = repositoryService;
365         }
366 }