/**
* (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jabylon.index.properties.impl;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.LockObtainFailedException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.common.notify.Notification;
import org.jabylon.index.properties.IndexActivator;
import org.jabylon.index.properties.QueryService;
import org.jabylon.properties.PropertyFileDescriptor;
import org.jabylon.resources.changes.PropertiesListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component
@Service
public class PropertyIndex extends Job implements PropertiesListener {
private static final Logger logger = LoggerFactory.getLogger(PropertyIndex.class);
BlockingQueue<DocumentTuple> writes;
public PropertyIndex() {
super("Index Job");
writes = new ArrayBlockingQueue<DocumentTuple>(50);
}
@Override
public void propertyFileAdded(PropertyFileDescriptor descriptor, boolean autoSync) {
PropertyFileAnalyzer analyzer = new PropertyFileAnalyzer();
List<Document> documents = analyzer.createDocuments(descriptor);
try {
writes.put(new DocumentTuple(documents));
schedule();
} catch (InterruptedException e) {
logger.warn("Interrupted",e);
}
}
@Override
public void propertyFileDeleted(PropertyFileDescriptor descriptor, boolean autoSync) {
try {
writes.put(new DocumentTuple(descriptor));
schedule();
} catch (InterruptedException e) {
logger.warn("Interrupted",e);
}
}
@Override
public void propertyFileModified(PropertyFileDescriptor descriptor, List<Notification> changes, boolean autoSync) {
PropertyFileAnalyzer analyzer = new PropertyFileAnalyzer();
List<Document> documents = analyzer.createDocuments(descriptor);
try {
writes.put(new DocumentTuple(descriptor, documents));
schedule();
} catch (InterruptedException e) {
logger.warn("Interrupted",e);
}
}
@Override
protected IStatus run(IProgressMonitor monitor) {
IndexWriter writer = null;
try {
writer = IndexActivator.getDefault().obtainIndexWriter();
while (true) {
DocumentTuple documentTuple = writes.poll(20,TimeUnit.SECONDS);
if (documentTuple == null)
break;
List<Document> documents = documentTuple.getDocuments();
switch (documentTuple.getAction()) {
case CREATE:
for (Document document : documents) {
writer.addDocument(document);
}
break;
case DELETE:
StringBuilder builder = new StringBuilder();
CDOIDUtil.write(builder, documentTuple.getDescriptor().cdoID());
writer.deleteDocuments(new Term(QueryService.FIELD_CDO_ID, builder.toString()));
break;
case REPLACE:
writer.deleteDocuments(new Term(QueryService.FIELD_FULL_PATH, documentTuple.getDescriptor().fullPath().toString()));
for (Document document : documents) {
writer.addDocument(document);
}
break;
default:
break;
}
}
writer.commit();
} catch (CorruptIndexException e) {
logger.error("Exception while indexing",e);
} catch (LockObtainFailedException e) {
logger.error("Exception while indexing",e);
} catch (IOException e) {
logger.error("Exception while indexing",e);
} catch (InterruptedException e) {
logger.warn("Interrupted while waiting for new index events",e);
} finally {
try {
IndexActivator.getDefault().returnIndexWriter(writer);
} catch (CorruptIndexException e) {
logger.error("Exception while closing index writer",e);
} catch (IOException e) {
logger.error("Exception while closing index writer",e);
}
}
return Status.OK_STATUS;
}
@Override
public boolean belongsTo(Object family) {
return IndexWriter.class == family;
}
}
class DocumentTuple {
private List<Document> docs;
private DocumentAction action;
private PropertyFileDescriptor descriptor;
public DocumentTuple(List<Document> docs) {
super();
this.docs = docs;
this.action = DocumentAction.CREATE;
}
public DocumentTuple(PropertyFileDescriptor descriptor) {
super();
this.descriptor = descriptor;
this.action = DocumentAction.DELETE;
}
public DocumentTuple(PropertyFileDescriptor descriptor, List<Document> docs) {
super();
this.descriptor = descriptor;
this.docs = docs;
this.action = DocumentAction.REPLACE;
}
public DocumentAction getAction() {
return action;
}
public List<Document> getDocuments() {
return docs;
}
public PropertyFileDescriptor getDescriptor() {
return descriptor;
}
}
enum DocumentAction {
CREATE, DELETE, REPLACE;
}