blob: 41c172685f8102210083c70055536ac1c7e7b327 [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.uima.caseditor.editor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.LinkedList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.ConstraintFactory;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIntConstraint;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FSMatchConstraint;
import org.apache.uima.cas.FeaturePath;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.impl.XCASDeserializer;
import org.apache.uima.cas.impl.XCASSerializer;
import org.apache.uima.cas.impl.XmiCasDeserializer;
import org.apache.uima.cas.impl.XmiCasSerializer;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.caseditor.CasEditorPlugin;
import org.apache.uima.caseditor.editor.util.Span;
import org.apache.uima.caseditor.editor.util.StrictTypeConstraint;
import org.apache.uima.util.XMLSerializer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.xml.sax.SAXException;
/**
* This document implementation is based on an uima cas object.
*/
public class DocumentUimaImpl extends AbstractDocument {
// TODO: Remove field not needed anymore
private final TypeSystem mTypeSystem;
private final CAS mCAS;
private final DocumentFormat format;
/**
* Initializes a new instance.
*
* @param project
*/
public DocumentUimaImpl(CAS cas, InputStream in, DocumentFormat format) throws CoreException {
mCAS = cas;
mTypeSystem = cas.getTypeSystem();
this.format = format;
setContent(in);
}
/**
* Retrieves the {@link CAS}.
*/
public CAS getCAS() {
return mCAS;
}
/**
* Adds the given annotation to the {@link CAS}.
*/
public void addFeatureStructure(FeatureStructure annotation) {
mCAS.getIndexRepository().addFS(annotation);
fireAddedFeatureStructure(annotation);
}
/**
*
*/
public void addFeatureStructures(Collection<? extends FeatureStructure> annotations) {
for (FeatureStructure annotation : annotations) {
addFeatureStructure(annotation);
}
}
/**
* Internally removes an annotation from the {@link CAS}.
*
* @param featureStructure
*/
private void removeAnnotationInternal(FeatureStructure featureStructure) {
getCAS().getIndexRepository().removeFS(featureStructure);
}
/**
* Removes the annotations from the {@link CAS}.
*/
public void removeFeatureStructure(FeatureStructure annotation) {
removeAnnotationInternal(annotation);
fireRemovedFeatureStructure(annotation);
}
/**
* Removes the given annotations from the {@link CAS}.
*/
public void removeFeatureStructures(Collection<? extends FeatureStructure> annotationsToRemove) {
for (FeatureStructure annotationToRemove : annotationsToRemove) {
removeAnnotationInternal(annotationToRemove);
}
if (annotationsToRemove.size() > 0) {
fireRemovedFeatureStructure(annotationsToRemove);
}
}
/**
* Notifies clients about the changed annotation.
*/
public void update(FeatureStructure annotation) {
fireUpdatedFeatureStructure(annotation);
}
/**
* Notifies clients about the changed annotation.
*/
public void updateFeatureStructure(Collection<? extends FeatureStructure> annotations) {
fireUpdatedFeatureStructure(annotations);
}
public void changed() {
fireChanged();
}
/**
* Retrieves annotations of the given type from the {@link CAS}.
*/
public Collection<AnnotationFS> getAnnotations(Type type) {
FSIndex<AnnotationFS> annotationIndex = mCAS.getAnnotationIndex(type);
StrictTypeConstraint typeConstrain = new StrictTypeConstraint(type);
FSIterator<AnnotationFS> strictTypeIterator =
mCAS.createFilteredIterator(annotationIndex.iterator(), typeConstrain);
return fsIteratorToCollection(strictTypeIterator);
}
private Collection<AnnotationFS> fsIteratorToCollection(FSIterator<AnnotationFS> iterator) {
LinkedList<AnnotationFS> annotations = new LinkedList<AnnotationFS>();
while (iterator.hasNext()) {
AnnotationFS annotation = (AnnotationFS) iterator.next();
annotations.addFirst(annotation);
}
return annotations;
}
/**
* Retrieves the annotations in the given span.
*/
@Override
public Collection<AnnotationFS> getAnnotation(Type type, Span span) {
ConstraintFactory cf = getCAS().getConstraintFactory();
Type annotationType = getCAS().getAnnotationType();
FeaturePath beginPath = getCAS().createFeaturePath();
beginPath.addFeature(annotationType.getFeatureByBaseName("begin"));
FSIntConstraint beginConstraint = cf.createIntConstraint();
beginConstraint.geq(span.getStart());
FSMatchConstraint embeddedBegin = cf.embedConstraint(beginPath, beginConstraint);
FeaturePath endPath = getCAS().createFeaturePath();
endPath.addFeature(annotationType.getFeatureByBaseName("end"));
FSIntConstraint endConstraint = cf.createIntConstraint();
endConstraint.leq(span.getEnd());
FSMatchConstraint embeddedEnd = cf.embedConstraint(endPath, endConstraint);
FSMatchConstraint strictType = new StrictTypeConstraint(type);
FSMatchConstraint annotatioInSpanConstraint = cf.and(embeddedBegin, embeddedEnd);
FSMatchConstraint annotationInSpanAndStrictTypeConstraint =
cf.and(annotatioInSpanConstraint, strictType);
FSIndex<AnnotationFS> allAnnotations = getCAS().getAnnotationIndex(type);
FSIterator<AnnotationFS> annotationInsideSpanIndex =
getCAS().createFilteredIterator(allAnnotations.iterator(),
annotationInSpanAndStrictTypeConstraint);
return fsIteratorToCollection(annotationInsideSpanIndex);
}
/**
* Retrieves the given type from the {@link TypeSystem}.
*/
public Type getType(String type) {
return getCAS().getTypeSystem().getType(type);
}
/**
* Sets the content. The XCAS {@link InputStream} gets parsed.
*/
private void setContent(InputStream content) throws CoreException {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setValidating(false);
SAXParser saxParser;
try {
saxParser = saxParserFactory.newSAXParser();
} catch (ParserConfigurationException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
} catch (SAXException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
if (DocumentFormat.XCAS.equals(format)) {
XCASDeserializer dezerializer = new XCASDeserializer(mTypeSystem);
try {
saxParser.parse(content, dezerializer.getXCASHandler(mCAS));
} catch (IOException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
} catch (SAXException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
} else if (DocumentFormat.XMI.equals(format)) {
XmiCasDeserializer dezerializer = new XmiCasDeserializer(mTypeSystem);
try {
saxParser.parse(content, dezerializer.getXmiCasHandler(mCAS));
} catch (IOException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
} catch (SAXException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
} else {
throw new CoreException(new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK,
"Unkown file format!", null));
}
}
/**
* Serializes the {@link CAS} to the given {@link OutputStream} in the XCAS format.
*/
public void serialize(OutputStream out) throws CoreException {
if (DocumentFormat.XCAS.equals(format)) {
XCASSerializer xcasSerializer = new XCASSerializer(mCAS.getTypeSystem());
XMLSerializer xmlSerialzer = new XMLSerializer(out, true);
try {
xcasSerializer.serialize(mCAS, xmlSerialzer.getContentHandler());
} catch (IOException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
} catch (SAXException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
} else if (DocumentFormat.XMI.equals(format)) {
XmiCasSerializer xmiSerializer = new XmiCasSerializer(mCAS.getTypeSystem());
XMLSerializer xmlSerialzer = new XMLSerializer(out, true);
try {
xmiSerializer.serialize(mCAS, xmlSerialzer.getContentHandler());
} catch (SAXException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
} else {
throw new CoreException(new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK,
"Unkown file format!", null));
}
}
}