/*******************************************************************************
* Copyright (c) 2009-2011 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.text.ext.hyperlink;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMemberValuePair;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.text.JavaWordFinder;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jboss.tools.seam.core.IBijectedAttribute;
import org.jboss.tools.seam.core.IRole;
import org.jboss.tools.seam.core.ISeamComponent;
import org.jboss.tools.seam.core.ISeamComponentDeclaration;
import org.jboss.tools.seam.core.ISeamContextShortVariable;
import org.jboss.tools.seam.core.ISeamContextVariable;
import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.ISeamXmlFactory;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.internal.core.SeamJavaComponentDeclaration;
import org.jboss.tools.seam.internal.core.el.SeamELCompletionEngine;
import org.jboss.tools.seam.text.ext.SeamExtPlugin;
/**
*
* @author Victor Rubezhny
*
*/
public class SeamComponentHyperlinkDetector extends AbstractHyperlinkDetector {
/*
* If the hyperlink is performed on the field name that is annotated as @In then
* the hyperlink will open a correspondent Seam component
*
* (non-Javadoc)
* @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion, boolean)
*/
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
ITextEditor textEditor= (ITextEditor)getAdapter(ITextEditor.class);
if (region == null ||
// canShowMultipleHyperlinks ||
!(textEditor instanceof JavaEditor))
return null;
int offset= region.getOffset();
IJavaElement input= EditorUtility.getEditorInputJavaElement(textEditor, false);
if (input == null)
return null;
if (input.getResource() == null || input.getResource().getProject() == null)
return null;
ISeamProject seamProject = SeamCorePlugin.getSeamProject(input.getResource().getProject(), true);
if(seamProject == null) {
return null;
}
SeamELCompletionEngine engine = new SeamELCompletionEngine();
IDocument document= textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
IRegion wordRegion= JavaWordFinder.findWord(document, offset);
if (wordRegion == null)
return null;
IFile file = null;
try {
IResource resource = input.getCorrespondingResource();
if (resource instanceof IFile)
file = (IFile) resource;
} catch (JavaModelException e) {
// It is probably because of Java element's resource is not found
SeamExtPlugin.getDefault().logError(e);
}
int[] range = new int[]{wordRegion.getOffset(), wordRegion.getOffset() + wordRegion.getLength()};
IJavaElement[] elements = null;
try {
elements = ((ICodeAssist)input).codeSelect(wordRegion.getOffset(), wordRegion.getLength());
if (elements == null)
return null;
if(elements.length != 1)
return null;
ArrayList<IHyperlink> hyperlinks = new ArrayList<IHyperlink>();
if (elements[0] instanceof IAnnotatable) {
IAnnotatable annotatable = (IAnnotatable)elements[0];
IAnnotation annotation = annotatable.getAnnotation("In");
if (annotation == null || !annotation.exists())
return null;
String nameToSearch = elements[0].getElementName();
IMemberValuePair[] mvPairs = annotation.getMemberValuePairs();
if (mvPairs != null) {
for (IMemberValuePair mvPair : mvPairs) {
if ("value".equals(mvPair.getMemberName()) && mvPair.getValue() != null) {
String name = mvPair.getValue().toString();
if (name != null && name.trim().length() != 0) {
nameToSearch = name;
break;
}
}
}
}
if (nameToSearch == null && nameToSearch.trim().length() == 0)
return null;
ISeamJavaComponentDeclaration declaration = null;
if(file != null) {
Set<ISeamComponent> cs = seamProject.getComponentsByPath(file.getFullPath());
for (ISeamComponent c: cs) {
ISeamJavaComponentDeclaration d = c.getJavaDeclaration();
if(d != null && file.getFullPath().equals(d.getSourcePath()) && !((SeamJavaComponentDeclaration)d).getImports().isEmpty()) {
declaration = d;
}
}
}
Set<ISeamContextVariable> vars = seamProject.getVariables(declaration);
if (vars != null) {
for (ISeamContextVariable var : vars) {
if (nameToSearch.equals(var.getName())){
while (var instanceof ISeamContextShortVariable) {
var = ((ISeamContextShortVariable)var).getOriginal();
}
if (var == null)
continue;
if (var instanceof ISeamXmlFactory) {
ISeamXmlFactory xmlFactory = (ISeamXmlFactory)var;
String value = xmlFactory.getValue();
if (value == null || value.trim().length() == 0) {
value = xmlFactory.getMethod();
}
if (value == null || value.trim().length() == 0)
continue;
List<IJavaElement> javaElements = null;
try {
javaElements = engine.getJavaElementsForExpression(
seamProject, file, value, region.getOffset());
} catch (StringIndexOutOfBoundsException e) {
SeamExtPlugin.getDefault().logError(e);
} catch (BadLocationException e) {
SeamExtPlugin.getDefault().logError(e);
}
if (javaElements != null) {
for (IJavaElement javaElement : javaElements) {
String resourceName = null;
if (javaElement.getResource() != null) {
resourceName=javaElement.getResource().getName();
}
hyperlinks.add(new SeamComponentHyperlink(wordRegion, resourceName, javaElement, nameToSearch));
}
}
} else if (var instanceof ISeamComponent) {
String resourceName = null;
ISeamComponent comp = (ISeamComponent)var;
Set<ISeamComponentDeclaration> decls = comp.getAllDeclarations();
for (ISeamComponentDeclaration decl : decls) {
if (decl.getResource() != null) {
resourceName = decl.getResource().getName();
break;
}
}
hyperlinks.add(new SeamComponentHyperlink(wordRegion, resourceName, (ISeamComponent)var, nameToSearch));
} else if (var instanceof IRole) {
String resourceName = null;
if (var.getResource() != null) {
resourceName = var.getResource().getName();
}
hyperlinks.add(new SeamComponentHyperlink(wordRegion, resourceName, (IRole)var, nameToSearch));
} else if (var instanceof IBijectedAttribute) {
String resourceName = null;
if (var.getResource() != null) {
resourceName = var.getResource().getName();
}
IBijectedAttribute attr = (IBijectedAttribute)var;
if (attr.getSourceMember() != null) {
hyperlinks.add(new SeamComponentHyperlink(wordRegion, resourceName, (IBijectedAttribute)var, nameToSearch));
}
}
}
}
}
}
if (hyperlinks != null && !hyperlinks.isEmpty()) {
return (IHyperlink[])hyperlinks.toArray(new IHyperlink[hyperlinks.size()]);
}
} catch (JavaModelException jme) {
SeamExtPlugin.getDefault().logError(jme);
}
return null;
}
}