blob: 4d09197e485546b00ff3719916cde34ad56df487 [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.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.uima.ResourceSpecifierFactory;
import org.apache.uima.UIMAFramework;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.SerialFormat;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.caseditor.CasEditorPlugin;
import org.apache.uima.caseditor.editor.util.StrictTypeConstraint;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.impl.ResourceManager_impl;
import org.apache.uima.resource.metadata.FsIndexDescription;
import org.apache.uima.resource.metadata.TypePriorities;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.resource.metadata.impl.FsIndexDescription_impl;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.CasIOUtils;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.apache.uima.util.XMLParser;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.preference.IPreferenceStore;
/**
* This document implementation is based on an uima cas object.
*/
public class DocumentUimaImpl extends AbstractDocument {
public static final String JAVA_NATURE = "org.eclipse.jdt.core.javanature";
private CAS mCAS;
private SerialFormat format = SerialFormat.XMI;
private final String typeSystemText;
/**
* Initializes a new instance.
*
* @param cas
* @param casFile
* @param typeSystemText
* type system string
*/
public DocumentUimaImpl(CAS cas, IFile casFile, String typeSystemText) throws CoreException {
mCAS = cas;
this.typeSystemText = typeSystemText;
setContent(casFile);
}
/**
* Retrieves the {@link CAS}.
*/
public CAS getCAS() {
return mCAS;
}
@Override
public String getTypeSystemText() {
return typeSystemText;
}
/**
* Internally removes an annotation from the {@link CAS}.
*
* @param featureStructure
*/
private void addFeatureStructureInternal(FeatureStructure featureStructure) {
getCAS().getIndexRepository().addFS(featureStructure);
}
/**
* Adds the given annotation to the {@link CAS}.
*/
public void addFeatureStructure(FeatureStructure annotation) {
addFeatureStructureInternal(annotation);
fireAddedFeatureStructure(annotation);
}
public void addFeatureStructures(Collection<? extends FeatureStructure> annotations) {
for (FeatureStructure annotation : annotations) {
addFeatureStructureInternal(annotation);
}
if (annotations.size() > 0) {
fireAddedFeatureStructure(annotations);
}
}
/**
* 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);
}
static 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 given type from the {@link TypeSystem}.
*/
public Type getType(String type) {
return getCAS().getTypeSystem().getType(type);
}
public void switchView(String viewName) {
String oldViewName = mCAS.getViewName();
mCAS = mCAS.getView(viewName);
fireViewChanged(oldViewName, viewName);
}
/**
* Sets the content. The XCAS {@link InputStream} gets parsed.
*/
private void setContent(IFile casFile) throws CoreException {
IPreferenceStore store = CasEditorPlugin.getDefault().getPreferenceStore();
boolean withPartialTypesystem = store
.getBoolean(AnnotationEditorPreferenceConstants.ANNOTATION_EDITOR_PARTIAL_TYPESYSTEM);
URI uri = casFile.getLocationURI();
if (casFile.isLinked()) {
uri = casFile.getRawLocationURI();
}
File file = EFS.getStore(uri).toLocalFile(0, new NullProgressMonitor());
try {
format = CasIOUtils.load(file.toURI().toURL(), null, mCAS, withPartialTypesystem);
} catch (IOException e) {
throwCoreException(e);
}
}
private void throwCoreException(Exception e) throws CoreException {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
/**
* Serializes the {@link CAS} to the given {@link OutputStream} in the XCAS format.
*/
public void serialize(OutputStream out) throws CoreException {
try {
CasIOUtils.save(mCAS, out, format);
} catch (IOException e) {
throwCoreException(e);
}
}
public static CAS getVirginCAS(IFile typeSystemFile) throws CoreException {
ResourceSpecifierFactory resourceSpecifierFactory = UIMAFramework.getResourceSpecifierFactory();
IFile extensionTypeSystemFile = typeSystemFile;
InputStream inTypeSystem;
if (extensionTypeSystemFile != null && extensionTypeSystemFile.exists()) {
inTypeSystem = extensionTypeSystemFile.getContents();
} else {
return null;
}
XMLInputSource xmlTypeSystemSource = new XMLInputSource(inTypeSystem,
extensionTypeSystemFile.getLocation().toFile());
XMLParser xmlParser = UIMAFramework.getXMLParser();
TypeSystemDescription typeSystemDesciptor;
try {
typeSystemDesciptor = (TypeSystemDescription) xmlParser.parse(xmlTypeSystemSource);
IProject project = typeSystemFile.getProject();
ClassLoader classLoader = getProjectClassLoader(project);
ResourceManager resourceManager = null;
if(classLoader != null) {
resourceManager = new ResourceManager_impl(classLoader);
} else {
resourceManager = UIMAFramework.newDefaultResourceManager();
}
String dataPath = project
.getPersistentProperty((new QualifiedName("", "CDEdataPath")));
if (dataPath != null) {
resourceManager.setDataPath(dataPath);
}
typeSystemDesciptor.resolveImports(resourceManager);
} catch (InvalidXMLException 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 (MalformedURLException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
TypePriorities typePriorities = resourceSpecifierFactory.createTypePriorities();
FsIndexDescription indexDesciptor = new FsIndexDescription_impl();
indexDesciptor.setLabel("TOPIndex");
indexDesciptor.setTypeName("uima.cas.TOP");
indexDesciptor.setKind(FsIndexDescription.KIND_SORTED);
CAS cas;
try {
cas = CasCreationUtils.createCas(typeSystemDesciptor, typePriorities,
new FsIndexDescription[] { indexDesciptor });
} catch (ResourceInitializationException e) {
String message = e.getMessage() != null ? e.getMessage() : "";
IStatus s = new Status(IStatus.ERROR, CasEditorPlugin.ID, IStatus.OK, message, e);
throw new CoreException(s);
}
return cas;
}
public static ClassLoader getProjectClassLoader(IProject project) throws CoreException {
IProjectNature javaNature = project.getNature(JAVA_NATURE);
if (javaNature != null) {
JavaProject javaProject = (JavaProject) JavaCore.create(project);
String[] runtimeClassPath = JavaRuntime.computeDefaultRuntimeClassPath(javaProject);
List<URL> urls = new ArrayList<>();
for (int i = 0; i < runtimeClassPath.length; i++) {
String cp = runtimeClassPath[i];
try {
urls.add(Paths.get(cp).toUri().toURL());
} catch (MalformedURLException e) {
CasEditorPlugin.log(e);
}
}
return new URLClassLoader(urls.toArray(new URL[0]));
}
return null;
}
}