/******************************************************************************* * Copyright (c) 2010 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.cdi.text.ext.hyperlink; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; 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.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.IFileEditorInput; import org.eclipse.ui.texteditor.ITextEditor; import org.jboss.tools.cdi.core.CDICoreNature; import org.jboss.tools.cdi.core.CDIUtil; import org.jboss.tools.cdi.core.IBean; import org.jboss.tools.cdi.core.ICDIProject; import org.jboss.tools.cdi.core.IClassBean; import org.jboss.tools.cdi.core.IInjectionPoint; import org.jboss.tools.cdi.core.IObserverMethod; import org.jboss.tools.cdi.core.IParameter; import org.jboss.tools.cdi.text.ext.CDIExtensionsPlugin; public class EventAndObserverMethodHyperlinkDetector extends AbstractHyperlinkDetector{ protected IFile file; public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { ITextEditor textEditor= (ITextEditor)getAdapter(ITextEditor.class); if (region == null || !(textEditor instanceof JavaEditor)) return null; if(textEditor.getEditorInput() instanceof IFileEditorInput){ file = ((IFileEditorInput)textEditor.getEditorInput()).getFile(); } int offset= region.getOffset(); ITypeRoot input= EditorUtility.getEditorInputJavaElement(textEditor, true); if (input == null) return null; IDocument document= textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); IRegion wordRegion= JavaWordFinder.findWord(document, offset); if (wordRegion == null) return null; IProject project = null; project = input.getJavaProject().getProject(); if(project == null) return null; CDICoreNature cdiNature = CDIUtil.getCDINatureWithProgress(project); if(cdiNature == null) return null; IJavaElement[] elements = null; try { elements = input.codeSelect(wordRegion.getOffset(), wordRegion.getLength()); if (elements == null) return null; if(elements.length != 1) return null; ArrayList<IHyperlink> hyperlinks = new ArrayList<IHyperlink>(); int position = 0; if(elements[0] instanceof IType){ elements[0] = input.getElementAt(wordRegion.getOffset()); if(elements[0] == null) return null; if(elements[0] instanceof IMethod){ position = offset; } } ICDIProject cdiProject = CDIUtil.getCDIProject(file, cdiNature, textEditor.isDirty()); if(cdiProject != null){ IInjectionPoint injectionPoint = findInjectedPoint(cdiProject, elements[0], position, input.getPath()); Set<IParameter> param = findObserverParameter(cdiProject, elements[0], offset, input.getPath()); if(injectionPoint != null){ Collection<IObserverMethod> observerMethods = cdiProject.resolveObserverMethods(injectionPoint); if(observerMethods.size() == 1){ hyperlinks.add(new ObserverMethodHyperlink(region, observerMethods.iterator().next(), document)); }else if(observerMethods.size() > 0){ hyperlinks.add(new ObserverMethodListHyperlink(textViewer, region, observerMethods, document)); } } else if(param != null) { Set<IInjectionPoint> events = new HashSet<IInjectionPoint>(); for (IParameter p: param) events.addAll(cdiProject.findObservedEvents(p)); if(events.size() == 1){ hyperlinks.add(new EventHyperlink(region, events.iterator().next(), document)); }else if(events.size() > 0){ hyperlinks.add(new EventListHyperlink(textViewer, region, events, document)); } } } if (hyperlinks != null && !hyperlinks.isEmpty()) { return (IHyperlink[])hyperlinks.toArray(new IHyperlink[hyperlinks.size()]); } } catch (JavaModelException jme) { CDIExtensionsPlugin.getDefault().logError(jme); } return null; } private IInjectionPoint findInjectedPoint(ICDIProject cdiProject, IJavaElement element, int offset, IPath path){ return CDIUtil.findInjectionPoint(cdiProject.getBeans(path), element, offset); } private Set<IParameter> findObserverParameter(ICDIProject cdiProject, IJavaElement element, int offset, IPath path) throws JavaModelException { HashSet<IParameter> result = new HashSet<IParameter>(); for (IBean bean: cdiProject.getBeans(path)) { if(bean instanceof IClassBean) { for (IObserverMethod bm: ((IClassBean)bean).getObserverMethods()) { ISourceRange sr = bm.getMethod().getSourceRange(); if(sr.getOffset() <= offset && sr.getOffset() + sr.getLength() >= offset) { IObserverMethod obs = (IObserverMethod)bm; Collection<IParameter> ps = obs.getObservedParameters(); if(!ps.isEmpty()) { result.add(ps.iterator().next()); } } } } } return result; } }