Java tutorial
/******************************************************************************* * Copyright (c) 2004, 2009 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are 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: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.java.ui.search; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IImportDeclaration; import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.ui.search.JavaSearchQuery; import org.eclipse.jdt.internal.ui.search.JavaSearchResult; import org.eclipse.jdt.ui.search.ElementQuerySpecification; import org.eclipse.jdt.ui.search.QuerySpecification; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.context.core.AbstractContextStructureBridge; import org.eclipse.mylyn.context.core.ContextCore; import org.eclipse.mylyn.context.core.IInteractionElement; import org.eclipse.mylyn.internal.context.core.AbstractRelationProvider; import org.eclipse.mylyn.internal.context.core.DegreeOfSeparation; import org.eclipse.mylyn.internal.context.core.IActiveSearchListener; import org.eclipse.mylyn.internal.context.core.IActiveSearchOperation; import org.eclipse.mylyn.internal.context.core.IDegreeOfSeparation; import org.eclipse.mylyn.internal.java.ui.JavaStructureBridge; import org.eclipse.mylyn.internal.java.ui.JavaUiBridgePlugin; import org.eclipse.mylyn.internal.resources.ui.ResourcesUiBridgePlugin; import org.eclipse.osgi.util.NLS; import org.eclipse.search.ui.ISearchResult; import org.eclipse.search2.internal.ui.InternalSearchUI; /** * @author Mik Kersten */ @SuppressWarnings("restriction") public abstract class AbstractJavaRelationProvider extends AbstractRelationProvider { public static final String ID_GENERIC = "org.eclipse.mylyn.java.relation"; //$NON-NLS-1$ public static final String NAME = "Java relationships"; //$NON-NLS-1$ private static final int DEFAULT_DEGREE = 2; private static final List<Job> runningJobs = new ArrayList<Job>(); @Override public String getGenericId() { return ID_GENERIC; } protected AbstractJavaRelationProvider(String structureKind, String id) { super(structureKind, id); } @Override public List<IDegreeOfSeparation> getDegreesOfSeparation() { List<IDegreeOfSeparation> separations = new ArrayList<IDegreeOfSeparation>(); separations.add(new DegreeOfSeparation(DOS_0_LABEL, 0)); separations.add(new DegreeOfSeparation(DOS_1_LABEL, 1)); separations.add(new DegreeOfSeparation(DOS_2_LABEL, 2)); separations.add(new DegreeOfSeparation(DOS_3_LABEL, 3)); separations.add(new DegreeOfSeparation(DOS_4_LABEL, 4)); separations.add(new DegreeOfSeparation(DOS_5_LABEL, 5)); return separations; } @Override protected void findRelated(final IInteractionElement node, int degreeOfSeparation) { if (node == null) { return; } if (node.getContentType() == null) { StatusHandler.log(new Status(IStatus.WARNING, JavaUiBridgePlugin.ID_PLUGIN, "Null content type for: " //$NON-NLS-1$ + node)); return; } if (!node.getContentType().equals(JavaStructureBridge.CONTENT_TYPE)) { return; } IJavaElement javaElement = JavaCore.create(node.getHandleIdentifier()); if (!acceptElement(javaElement) || !javaElement.exists() || javaElement instanceof IInitializer) { return; } IJavaSearchScope scope = createJavaSearchScope(javaElement, degreeOfSeparation); if (scope != null) { runJob(node, degreeOfSeparation, getId()); } } private IJavaSearchScope createJavaSearchScope(IJavaElement element, int degreeOfSeparation) { Set<IInteractionElement> landmarks = ContextCore.getContextManager().getActiveLandmarks(); List<IInteractionElement> interestingElements = ContextCore.getContextManager().getActiveContext() .getInteresting(); Set<IJavaElement> searchElements = new HashSet<IJavaElement>(); int includeMask = IJavaSearchScope.SOURCES; if (degreeOfSeparation == 1) { for (IInteractionElement landmark : landmarks) { AbstractContextStructureBridge bridge = ContextCore.getStructureBridge(landmark.getContentType()); if (includeNodeInScope(landmark, bridge)) { Object o = bridge.getObjectForHandle(landmark.getHandleIdentifier()); if (o instanceof IJavaElement) { IJavaElement landmarkElement = (IJavaElement) o; if (landmarkElement.exists()) { if (landmarkElement instanceof IMember && !landmark.getInterest().isPropagated()) { searchElements.add(((IMember) landmarkElement).getCompilationUnit()); } else if (landmarkElement instanceof ICompilationUnit) { searchElements.add(landmarkElement); } } } } } } else if (degreeOfSeparation == 2) { for (IInteractionElement interesting : interestingElements) { AbstractContextStructureBridge bridge = ContextCore .getStructureBridge(interesting.getContentType()); if (includeNodeInScope(interesting, bridge)) { Object object = bridge.getObjectForHandle(interesting.getHandleIdentifier()); if (object instanceof IJavaElement) { IJavaElement interestingElement = (IJavaElement) object; if (interestingElement.exists()) { if (interestingElement instanceof IMember && !interesting.getInterest().isPropagated()) { searchElements.add(((IMember) interestingElement).getCompilationUnit()); } else if (interestingElement instanceof ICompilationUnit) { searchElements.add(interestingElement); } } } } } } else if (degreeOfSeparation == 3 || degreeOfSeparation == 4) { for (IInteractionElement interesting : interestingElements) { AbstractContextStructureBridge bridge = ContextCore .getStructureBridge(interesting.getContentType()); if (includeNodeInScope(interesting, bridge)) { // TODO what to do when the element is not a java element, // how determine if a javaProject? IResource resource = ResourcesUiBridgePlugin.getDefault().getResourceForElement(interesting, true); if (resource != null) { IProject project = resource.getProject(); if (project != null && JavaProject.hasJavaNature(project) && project.exists()) { IJavaProject javaProject = JavaCore.create(project);// ((IJavaElement)o).getJavaProject(); if (javaProject != null && javaProject.exists()) { searchElements.add(javaProject); } } } } } if (degreeOfSeparation == 4) { includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES; } } else if (degreeOfSeparation == 5) { return SearchEngine.createWorkspaceScope(); } if (searchElements.size() == 0) { return null; } else { IJavaElement[] elements = new IJavaElement[searchElements.size()]; int j = 0; for (IJavaElement searchElement : searchElements) { elements[j] = searchElement; j++; } return SearchEngine.createJavaSearchScope(elements, includeMask); } } /** * Only include Java elements and files. */ private boolean includeNodeInScope(IInteractionElement interesting, AbstractContextStructureBridge bridge) { if (interesting == null || bridge == null) { return false; } else { if (interesting.getContentType() == null) { // TODO: remove StatusHandler .log(new Status(IStatus.WARNING, JavaUiBridgePlugin.ID_PLUGIN, "Null content type for: " //$NON-NLS-1$ + interesting.getHandleIdentifier())); return false; } else { return interesting.getContentType().equals(JavaStructureBridge.CONTENT_TYPE) || bridge.isDocument(interesting.getHandleIdentifier()); } } } protected boolean acceptResultElement(IJavaElement element) { return !(element instanceof IImportDeclaration); } protected boolean acceptElement(IJavaElement javaElement) { return javaElement != null && (javaElement instanceof IMember || javaElement instanceof IType); } private void runJob(final IInteractionElement node, final int degreeOfSeparation, final String kind) { int limitTo = 0; if (kind.equals(JavaReferencesProvider.ID)) { limitTo = IJavaSearchConstants.REFERENCES; } else if (kind.equals(JavaImplementorsProvider.ID)) { limitTo = IJavaSearchConstants.IMPLEMENTORS; } else if (kind.equals(JUnitReferencesProvider.ID)) { limitTo = IJavaSearchConstants.REFERENCES; } else if (kind.equals(JavaReadAccessProvider.ID)) { limitTo = IJavaSearchConstants.REFERENCES; } else if (kind.equals(JavaWriteAccessProvider.ID)) { limitTo = IJavaSearchConstants.REFERENCES; } final JavaSearchOperation query = (JavaSearchOperation) getSearchOperation(node, limitTo, degreeOfSeparation); if (query == null) { return; } JavaSearchJob job = new JavaSearchJob(query.getLabel(), query); query.addListener(new IActiveSearchListener() { private boolean gathered = false; public boolean resultsGathered() { return gathered; } @SuppressWarnings("rawtypes") public void searchCompleted(List l) { if (l == null) { return; } List<IJavaElement> relatedHandles = new ArrayList<IJavaElement>(); Object[] elements = l.toArray(); for (Object element : elements) { if (element instanceof IJavaElement) { relatedHandles.add((IJavaElement) element); } } for (IJavaElement element : relatedHandles) { if (!acceptResultElement(element)) { continue; } incrementInterest(node, JavaStructureBridge.CONTENT_TYPE, element.getHandleIdentifier(), degreeOfSeparation); } gathered = true; AbstractJavaRelationProvider.this.searchCompleted(node); } }); InternalSearchUI.getInstance(); runningJobs.add(job); job.setPriority(Job.DECORATE - 10); job.schedule(); } @Override public IActiveSearchOperation getSearchOperation(IInteractionElement node, int limitTo, int degreeOfSeparation) { IJavaElement javaElement = JavaCore.create(node.getHandleIdentifier()); if (javaElement == null || !javaElement.exists()) { return null; } IJavaSearchScope scope = createJavaSearchScope(javaElement, degreeOfSeparation); if (scope == null) { return null; } QuerySpecification specs = new ElementQuerySpecification(javaElement, limitTo, scope, Messages.AbstractJavaRelationProvider_Mylyn_degree_of_separation + degreeOfSeparation); return new JavaSearchOperation(specs); } protected static class JavaSearchJob extends Job { private final JavaSearchOperation op; public JavaSearchJob(String name, JavaSearchOperation op) { super(name); this.op = op; } /** * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected IStatus run(IProgressMonitor monitor) { return op.run(monitor); } } protected static class JavaSearchOperation extends JavaSearchQuery implements IActiveSearchOperation { private ISearchResult result = null; @Override public ISearchResult getSearchResult() { if (result == null) { result = new JavaSearchResult(this); } new JavaActiveSearchResultUpdater((JavaSearchResult) result); return result; } @Override public IStatus run(IProgressMonitor monitor) { IStatus runStatus = super.run(monitor); ISearchResult result = getSearchResult(); if (result instanceof JavaSearchResult) { Object[] objs = ((JavaSearchResult) result).getElements(); if (objs == null) { notifySearchCompleted(null); } else { List<Object> l = new ArrayList<Object>(); for (Object obj : objs) { l.add(obj); } notifySearchCompleted(l); } } return runStatus; } /** * Constructor * * @param data */ public JavaSearchOperation(QuerySpecification data) { super(data); } /** List of listeners wanting to know about the searches */ private final List<IActiveSearchListener> listeners = new ArrayList<IActiveSearchListener>(); /** * Add a listener for when the bugzilla search is completed * * @param l * The listener to add */ public void addListener(IActiveSearchListener l) { // add the listener to the list listeners.add(l); } /** * Remove a listener for when the bugzilla search is completed * * @param l * The listener to remove */ public void removeListener(IActiveSearchListener l) { // remove the listener from the list listeners.remove(l); } /** * Notifies all of the listeners that the bugzilla search is completed * * @param doiList * A list of BugzillaSearchHitDoiInfo * @param member * The IMember that the search was performed on */ public void notifySearchCompleted(final List<Object> l) { for (final IActiveSearchListener listener : listeners) { SafeRunner.run(new ISafeRunnable() { public void run() throws Exception { listener.searchCompleted(l); } public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, JavaUiBridgePlugin.ID_PLUGIN, NLS.bind("Unexpected error during listener invocation: {0}", listener.getClass()), //$NON-NLS-1$ e)); } }); } } } @Override public void stopAllRunningJobs() { for (Job j : runningJobs) { j.cancel(); } runningJobs.clear(); } @Override protected int getDefaultDegreeOfSeparation() { return DEFAULT_DEGREE; } }