blob: 9350c2663c0ad59970cfba6afa8d3ed00e357e2f [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.ruta.ide.ui.text;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.uima.UIMAFramework;
import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.metadata.TypeDescription;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.ruta.ide.core.builder.RutaProjectUtils;
import org.apache.uima.ruta.ide.core.codeassist.RutaReferenceVisitor;
import org.apache.uima.ruta.ide.core.codeassist.RutaSelectionParser;
import org.apache.uima.ruta.ide.parser.ast.RutaModuleDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaTypeConstants;
import org.apache.uima.ruta.ide.parser.ast.RutaVariableReference;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.compiler.env.ISourceModule;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.dltk.internal.ui.editor.ScriptEditor;
import org.eclipse.dltk.internal.ui.text.ScriptWordFinder;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.ui.texteditor.ITextEditor;
public class ExternalTypeHyperlinkDetector implements IHyperlinkDetector {
private ITextEditor fTextEditor;
public ExternalTypeHyperlinkDetector(ITextEditor editor) {
Assert.isNotNull(editor);
fTextEditor = editor;
}
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region,
boolean canShowMultipleHyperlinks) {
if (region == null || !(fTextEditor instanceof ScriptEditor))
return null;
int offset = region.getOffset();
IModelElement input = EditorUtility.getEditorInputModelElement(fTextEditor, false);
if (input == null)
return null;
try {
IDocument document = fTextEditor.getDocumentProvider().getDocument(
fTextEditor.getEditorInput());
IRegion wordRegion = ScriptWordFinder.findWord(document, offset);
if (wordRegion == null)
return null;
if (input instanceof ISourceModule) {
ISourceModule sm = (ISourceModule) input;
IModelElement modelElement = sm.getModelElement();
RutaSelectionParser parser = new RutaSelectionParser();
ModuleDeclaration moduleDeclaration = parser.parse(sm);
String word = document.get(wordRegion.getOffset(), wordRegion.getLength());
RutaReferenceVisitor referenceVisitor = new RutaReferenceVisitor(wordRegion.getOffset());
moduleDeclaration.traverse(referenceVisitor);
ASTNode node = referenceVisitor.getResult();
if (node instanceof RutaVariableReference
&& moduleDeclaration instanceof RutaModuleDeclaration) {
RutaVariableReference vr = (RutaVariableReference) node;
RutaModuleDeclaration parsed = (RutaModuleDeclaration) moduleDeclaration;
if (vr.getType() == RutaTypeConstants.RUTA_TYPE_AT) {
String nodeText = vr.getStringRepresentation();
Collection<String> importedTypeSystems = parsed.descriptorInfo.getImportedTypeSystems();
List<IHyperlink> result = new ArrayList<IHyperlink>();
for (String tsString : importedTypeSystems) {
IFolder folder = modelElement.getScriptProject().getProject()
.getFolder(RutaProjectUtils.getDefaultDescriptorLocation());
String xmlFilePath = tsString.replaceAll("\\.", "/");
xmlFilePath = xmlFilePath.substring(0, xmlFilePath.length()) + ".xml";
Set<String> types = getTypes(folder, xmlFilePath);
if (types.contains(nodeText)) {
IFile iFile = getFile(folder, xmlFilePath);
IHyperlink link = new ExternalTypeHyperlink(nodeText, wordRegion, iFile, tsString,
fTextEditor);
result.add(link);
}
}
if (!result.isEmpty()) {
return result.toArray(new IHyperlink[] {});
} else {
return null;
}
}
}
}
} catch (Exception e) {
return null;
}
return null;
}
private Set<String> getTypes(IFolder folder, String filePath) throws InvalidXMLException,
IOException {
Set<String> types = new HashSet<String>();
IFile iFile = getFile(folder, filePath);
URL url;
try {
url = iFile.getLocationURI().toURL();
ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
resMgr.setDataPath(folder.getLocation().toPortableString());
types = getTypes(url, resMgr);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return types;
}
private Set<String> getTypes(URL resource, ResourceManager resMgr) throws IOException,
InvalidXMLException {
Set<String> types = new HashSet<String>();
TypeSystemDescription typeSysDescr = null;
typeSysDescr = UIMAFramework.getXMLParser().parseTypeSystemDescription(
new XMLInputSource(resource));
typeSysDescr.resolveImports(resMgr);
for (TypeDescription each : typeSysDescr.getTypes()) {
String name = each.getName();
String[] nameSpace = name.split("[.]");
types.add(nameSpace[nameSpace.length - 1]);
StringBuffer fullName = new StringBuffer();
if (nameSpace.length > 0) {
fullName.append(nameSpace[0]);
}
for (int i = 1; i < nameSpace.length; i++) {
// TODO fix workaround
if (!nameSpace[i].equals("type")) {
fullName.append('.');
fullName.append(nameSpace[i]);
}
}
types.add(fullName.toString());
}
return types;
}
private IFile getFile(IFolder folder, String filePath) {
int lastDot = filePath.lastIndexOf('.');
int sndLastDot = filePath.lastIndexOf('.', lastDot - 1);
String fName = filePath;
if (sndLastDot >= 0) {
String subFolder = filePath.substring(0, sndLastDot);
folder = folder.getFolder(subFolder);
fName = filePath.substring(sndLastDot + 1);
}
return folder.getFile(fName);
}
}