1 package org.splat.service.technical;
5 * @author Daniel Brunier-Coulin
6 * @copyright OPEN CASCADE 2012-2015
10 import java.io.IOException;
11 import java.io.Serializable;
12 import java.util.Iterator;
13 import java.util.List;
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;
38 * Implementation of the service for work with Lucen index.
40 public class IndexServiceImpl implements IndexService {
43 * The logger for this service.
45 private static final Logger LOG = Logger.getLogger(IndexServiceImpl.class);
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";
53 private transient Directory _index;
54 private transient org.apache.lucene.document.Document _body;
55 private ProjectElementService _projectElementService;
56 private RepositoryService _repositoryService;
58 protected static StandardAnalyzer analyzer = new StandardAnalyzer(
61 private class Entry extends IndexWriter {
62 private transient final org.apache.lucene.document.Document _entry;
64 private Entry(final Study study) throws CorruptIndexException,
65 LockObtainFailedException, IOException {
66 super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
68 // Addition of mandatory fields
69 _entry = new org.apache.lucene.document.Document();
71 field = _body.getField(PROP_INDEX);
72 field.setValue(String.valueOf(study.getIndex()));
74 field = _body.getField("class");
75 field.setValue("Study");
77 field = _body.getField("type");
78 field.setValue(""); // Reserved for configurable Study type
80 field = _body.getField(PROP_REF);
81 field.setValue(study.getReference());
83 field = _body.getField("area");
84 field.setValue(study.getVisibility().toString());
86 field = _body.getField(PROP_STATE);
87 field.setValue(study.getProgressState().toString());
89 field = _body.getField(PROP_AUTHOR);
90 field.setValue(study.getAuthor().toString());
92 field = _body.getField(PROP_TITLE);
93 field.setValue(study.getTitle());
95 field = _body.getField("contents");
96 field.setValue(study.getTitle());
99 // Addition of optional fields
101 setContextAt(getProjectElementService().getSteps(study));
104 private Entry(final KnowledgeElement kelm)
105 throws CorruptIndexException, LockObtainFailedException,
107 super(_index, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
109 // Addition of mandatory fields
110 _entry = new org.apache.lucene.document.Document();
112 field = _body.getField(PROP_INDEX);
113 field.setValue(String.valueOf(kelm.getIndex()));
115 field = _body.getField("class");
116 field.setValue("KnowledgeElement");
118 field = _body.getField("type");
119 field.setValue(kelm.getType().getName());
121 field = _body.getField(PROP_REF);
122 field.setValue(kelm.getReference());
124 field = _body.getField("area");
125 field.setValue(kelm.getVisibility().toString());
127 field = _body.getField(PROP_STATE);
128 field.setValue(kelm.getProgressState().toString());
130 field = _body.getField(PROP_AUTHOR);
131 field.setValue(kelm.getAuthor().toString());
133 field = _body.getField(PROP_TITLE);
134 field.setValue(kelm.getTitle());
136 field = _body.getField("contents");
137 field.setValue(kelm.getTitle());
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));
148 private void add() throws CorruptIndexException, IOException {
151 // Save the new entry
152 optimize(); // Should be called before committing the index
153 close(); // Commits the index
155 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
156 .getRepositoryIndexDirectory()))) {
157 IndexWriter.unlock(FSDirectory.open(getRepositoryService()
158 .getRepositoryIndexDirectory()));
163 private void update() throws CorruptIndexException, IOException {
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
172 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
173 .getRepositoryIndexDirectory()))) {
174 IndexWriter.unlock(FSDirectory.open(getRepositoryService()
175 .getRepositoryIndexDirectory()));
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
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));
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: "
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);
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;
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);
232 public String getAuthorName() {
236 public Long getIndex() {
240 public ProgressState getProgressState() {
244 public String getReference() {
248 public String getTitle() {
252 public String getType() {
257 // ==============================================================================================================================
259 // ==============================================================================================================================
261 public void configure() throws IOException {
262 File indir = getRepositoryService().getRepositoryIndexDirectory();
263 if (_index != null) {
267 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
268 .getRepositoryIndexDirectory()))) {
269 IndexWriter.unlock(FSDirectory.open(getRepositoryService()
270 .getRepositoryIndexDirectory()));
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
299 public void create() throws IOException {
300 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
301 .getRepositoryIndexDirectory()))) {
302 IndexWriter.unlock(FSDirectory.open(getRepositoryService()
303 .getRepositoryIndexDirectory()));
305 Directory index = FSDirectory.open(getRepositoryService()
306 .getRepositoryIndexDirectory());
307 if (IndexWriter.isLocked(index)) {
308 IndexWriter.unlock(index);
310 IndexWriter writer = null;
312 writer = new IndexWriter(index, analyzer, true,
313 IndexWriter.MaxFieldLength.UNLIMITED);
315 if (writer != null) {
318 writer.close(); // ==== Creates an empty index
320 if (IndexWriter.isLocked(index)) {
321 IndexWriter.unlock(index);
328 // ==============================================================================================================================
330 // ==============================================================================================================================
332 public void add(final Study study) throws IOException {
333 IndexServiceImpl.Entry entry = new Entry(study);
335 if (LOG.isInfoEnabled()) {
336 LOG.info("Study \"" + study.getIndex() + "\" indexed.");
340 public void add(final KnowledgeElement kelm) throws IOException {
341 IndexServiceImpl.Entry entry = new Entry(kelm);
343 if (LOG.isInfoEnabled()) {
344 LOG.info("Knowledge \"" + kelm.getIndex() + "\" indexed.");
348 public boolean exists() {
351 res = IndexReader.indexExists(_index);
352 } catch (IOException error) {
353 LOG.error(error.getMessage(), error);
358 public void update(final Study study) throws IOException {
359 IndexServiceImpl.Entry entry = new Entry(study);
361 if (LOG.isInfoEnabled()) {
362 LOG.info("Study \"" + study.getIndex() + "\" re-indexed.");
366 public void update(final KnowledgeElement kelm) throws IOException {
367 IndexServiceImpl.Entry entry = new Entry(kelm);
369 if (LOG.isInfoEnabled()) {
370 LOG.info("Knowledge \"" + kelm.getIndex() + "\" re-indexed.");
375 * Get the projectElementService.
377 * @return the projectElementService
379 public ProjectElementService getProjectElementService() {
380 return _projectElementService;
384 * Set the projectElementService.
386 * @param projectElementService
387 * the projectElementService to set
389 public void setProjectElementService(
390 final ProjectElementService projectElementService) {
391 _projectElementService = projectElementService;
395 * Get the repositoryService.
397 * @return the repositoryService
399 public RepositoryService getRepositoryService() {
400 return _repositoryService;
404 * Set the repositoryService.
406 * @param repositoryService
407 * the repositoryService to set
409 public void setRepositoryService(final RepositoryService repositoryService) {
410 _repositoryService = repositoryService;