blob: 6a84085aa694aa096102c8136747f284179d9972 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.opennlp.caseditor.sentdetect;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import opennlp.tools.util.Span;
import org.apache.opennlp.caseditor.AbstractCasChangeTrigger;
import org.apache.opennlp.caseditor.OpenNLPPlugin;
import org.apache.opennlp.caseditor.OpenNLPPreferenceConstants;
import org.apache.opennlp.caseditor.PotentialAnnotation;
import org.apache.opennlp.caseditor.namefinder.EntityContentProvider;
import org.apache.opennlp.caseditor.util.UIMAUtil;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.caseditor.editor.AnnotationEditor;
import org.apache.uima.caseditor.editor.ICasDocument;
import org.apache.uima.caseditor.editor.ICasDocumentListener;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
public class SentenceContentProvider implements IStructuredContentProvider {
private class CasChangeSDTrigger extends AbstractCasChangeTrigger {
@Override
protected void trigger() {
triggerSentenceDetector();
}
}
/**
* Listeners which triggers a run of the name finder when a related preferences changed.
*/
private class PreferenceChangeTrigger implements IPropertyChangeListener{
@Override
public void propertyChange(PropertyChangeEvent event) {
// Filter all changes of preferences which do not belong to this plugin
if (event.getProperty().startsWith(OpenNLPPlugin.ID)) {
triggerSentenceDetector();
}
}
}
private SentenceDetectorViewPage sentenceDetectorView;
private AnnotationEditor editor;
private ICasDocumentListener casChangedTrigger;
private PreferenceChangeTrigger preferenceChangeTrigger = new PreferenceChangeTrigger();
private SentenceDetectorJob sentenceDetector;
private TableViewer sentenceList;
public SentenceContentProvider(SentenceDetectorViewPage sentenceDetectorView, AnnotationEditor editor,
SentenceDetectorJob sentenceDetector, TableViewer sentenceList) {
this.sentenceDetectorView = sentenceDetectorView;
this.editor = editor;
this.sentenceDetector = sentenceDetector;
this.sentenceList = sentenceList;
sentenceDetector.addJobChangeListener(new JobChangeAdapter() {
public void done(final IJobChangeEvent event) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (event.getResult().isOK()) {
SentenceContentProvider.this.sentenceDetectorView.setMessage(null);
List<PotentialAnnotation> confirmedSentences = new ArrayList<PotentialAnnotation>();
// TODO: Create a list of existing sentence annotations.
// get sentence annotation index ...
CAS cas = SentenceContentProvider.this.editor.getDocument().getCAS();
IPreferenceStore store = SentenceContentProvider.this.editor.
getCasDocumentProvider().getTypeSystemPreferenceStore(
SentenceContentProvider.this.editor.getEditorInput());
String sentenceTypeName = store.getString(OpenNLPPreferenceConstants.SENTENCE_TYPE);;
Type sentenceType = cas.getTypeSystem().getType(sentenceTypeName);
for (Iterator<AnnotationFS> it = cas.getAnnotationIndex(sentenceType).iterator();
it.hasNext(); ) {
AnnotationFS sentenceAnnotation = it.next();
confirmedSentences.add(new PotentialAnnotation(sentenceAnnotation.getBegin(),
sentenceAnnotation.getEnd(), sentenceAnnotation.getCoveredText(), 1d, sentenceTypeName));
}
PotentialAnnotation sentences[] = SentenceContentProvider.this.
sentenceDetector.getDetectedSentences();
// TODO:
// Remove all detected sentences from the last run which are not detected anymore
Table sentenceTable = SentenceContentProvider.this.sentenceList.getTable();
int selectionIndex = sentenceTable.getSelectionIndex();
SentenceContentProvider.this.sentenceList.refresh();
// TODO: Update sentence if it already exist
// Add a new potential sentence
// Only add if it is not a confirmed sentence yet!
// for each annotation, search confirmed sentence array above ...
for (PotentialAnnotation sentence : sentences) {
if (EntityContentProvider.searchEntity(confirmedSentences,
sentence.getBeginIndex(), sentence.getEndIndex(),
sentence.getType()) == null) {
SentenceContentProvider.this.sentenceList.add(sentence);
}
}
// TODO: Try to reuse selection computation code
// is sentence detector view active ?!
if (SentenceContentProvider.this.sentenceDetectorView.isActive()) {
int newSelectionIndex = -1;
if (sentenceTable.getItemCount() > 0) {
if (sentenceTable.getSelectionIndex() == -1) {
newSelectionIndex = 0;
}
if (selectionIndex < sentenceTable.getItemCount()) {
newSelectionIndex = selectionIndex;
}
else if (selectionIndex >= sentenceTable.getItemCount()) {
newSelectionIndex = sentenceTable.getItemCount() - 1;
}
}
if (newSelectionIndex != -1) {
SentenceContentProvider.this.sentenceList.setSelection(
new StructuredSelection(SentenceContentProvider.this.sentenceList.getElementAt(newSelectionIndex)));
}
}
}
else {
SentenceContentProvider.this.sentenceDetectorView.setMessage(event.getResult().getMessage());
}
}
});
}
});
IPreferenceStore store = editor.getCasDocumentProvider().getTypeSystemPreferenceStore(editor.getEditorInput());
store.addPropertyChangeListener(preferenceChangeTrigger);
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// Clears the sentence list
sentenceList.refresh();
if (oldInput != null) {
((ICasDocument) oldInput).removeChangeListener(casChangedTrigger);
}
if (newInput != null) {
ICasDocument document = (ICasDocument) newInput;
casChangedTrigger = new CasChangeSDTrigger();
document.addChangeListener(casChangedTrigger);
triggerSentenceDetector();
}
}
void triggerSentenceDetector() {
IPreferenceStore store = editor.getCasDocumentProvider().getTypeSystemPreferenceStore(editor.getEditorInput());
CAS cas = editor.getDocument().getCAS();
String paragraphTypeNames = store.getString(OpenNLPPreferenceConstants.PARAGRAPH_TYPE);
Type paragraphTypes[] = UIMAUtil.splitTypes(paragraphTypeNames, ',', cas.getTypeSystem());
List<Span> paragraphSpans = new ArrayList<Span>();
if (paragraphTypes != null) {
for (Iterator<AnnotationFS> sentenceIterator = UIMAUtil.createMultiTypeIterator(cas, paragraphTypes);
sentenceIterator.hasNext();) {
AnnotationFS paragraphAnnotation = sentenceIterator.next();
paragraphSpans.add(
new Span(paragraphAnnotation.getBegin(), paragraphAnnotation.getEnd()));
}
}
else {
if (paragraphTypeNames.trim().isEmpty()) {
paragraphSpans.add(new Span(0, cas.getDocumentText().length()));
}
else {
sentenceDetectorView.setMessage("A paragraph type cannot be found in the type system!");
return;
}
}
sentenceDetector.setParagraphs(paragraphSpans);
String sentenceTypeName = store.getString(OpenNLPPreferenceConstants.SENTENCE_TYPE);
if (sentenceTypeName.isEmpty()) {
sentenceDetectorView.setMessage("Sentence type name is not set!");
return;
}
Type sentenceType = cas.getTypeSystem().getType(sentenceTypeName);
// TODO: Add all existing sentences to the exclusion spans ...
if (sentenceType == null) {
sentenceDetectorView.setMessage("Type system does not contain sentence type!");
return;
}
sentenceDetector.setSentenceType(sentenceType.getName());
String exclusionSpanTypeNames = store.getString(OpenNLPPreferenceConstants.SENT_EXCLUSION_TYPE);
Type exclusionSpanTypes[] = UIMAUtil.splitTypes(exclusionSpanTypeNames, ',', cas.getTypeSystem());
if (exclusionSpanTypes == null) {
exclusionSpanTypes = new Type[0];
}
if (Arrays.binarySearch(exclusionSpanTypes, sentenceType) < 0) {
exclusionSpanTypes = Arrays.copyOf(exclusionSpanTypes, exclusionSpanTypes.length + 1);
exclusionSpanTypes[exclusionSpanTypes.length - 1] = sentenceType;
}
List<Span> exclusionSpans = new ArrayList<Span>();
for (Iterator<AnnotationFS> exclusionAnnIterator = UIMAUtil.createMultiTypeIterator(cas, exclusionSpanTypes);
exclusionAnnIterator.hasNext();) {
AnnotationFS exclusionAnnotation = exclusionAnnIterator.next();
exclusionSpans.add(new Span(exclusionAnnotation.getBegin(), exclusionAnnotation.getEnd()));
}
sentenceDetector.setExclusionSpans(exclusionSpans);
String modelPath = store.getString(OpenNLPPreferenceConstants.SENTENCE_DETECTOR_MODEL_PATH);
sentenceDetector.setModelPath(modelPath);
sentenceDetector.setText(editor.getDocument().getCAS().getDocumentText());
sentenceDetector.schedule();
}
@Override
public Object[] getElements(Object inputElement) {
return new Object[0];
}
@Override
public void dispose() {
IPreferenceStore store = editor.getCasDocumentProvider().getTypeSystemPreferenceStore(editor.getEditorInput());
store.removePropertyChangeListener(preferenceChangeTrigger);
}
}