/*******************************************************************************
* Copyright (c) 2012 VMWare, Inc.
* 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:
* VMWare, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.search;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.ui.search.ISearchRequestor;
import org.grails.ide.eclipse.core.GrailsCoreActivator;
import org.grails.ide.eclipse.core.internal.plugins.GrailsCore;
import org.grails.ide.eclipse.editor.groovy.controllers.ControllerTarget;
import org.grails.ide.eclipse.editor.groovy.controllers.PerProjectControllerCache;
import org.grails.ide.eclipse.editor.groovy.elements.GrailsProject;
/**
* @author Kris De Volder
*
* @since 2.9
*/
public abstract class AbstractGrailsSearch {
public AbstractGrailsSearch() {
}
/**
* The types to search for references in (should be a list of toplevel types)
*/
protected List<IType> typesToSearch = new ArrayList<IType>();
/**
* The gsp files to search for references in (should be a list of gsp files)
*/
protected List<IFile> gspFilesToSearch = new ArrayList<IFile>();
/**
* The URLMappings file to search.
*/
protected IFile urlMappingsToSearch = null;
/**
* If this method returns false, the search can be ignored since it won't find any results. If it returns true, it
* may or may not find results.
*/
public boolean isInteresting() {
return !typesToSearch.isEmpty() || !gspFilesToSearch.isEmpty() || urlMappingsToSearch!=null;
}
public boolean add(IType elementToSearchIn) {
return typesToSearch.add(elementToSearchIn);
}
public void perform(ISearchRequestor requestor) {
for (IType searchType : typesToSearch) {
ICompilationUnit cu = searchType.getCompilationUnit();
if (cu!=null) {
SearchingCodeVisitor visitor = createSearchingVisitor(requestor, cu);
visitor.start();
}
}
for (IFile gspFile : gspFilesToSearch) {
FileSearcher searcher = createGSPSearcher(requestor, gspFile);
safePerform(searcher);
}
if (urlMappingsToSearch!=null) {
FileSearcher searcher = createURLMappingSearcher(requestor, urlMappingsToSearch);
safePerform(searcher);
}
}
public void safePerform(FileSearcher searcher) {
try {
if (searcher!=null) {
searcher.perform();
}
} catch (CoreException e) {
GrailsCoreActivator.log(e);
} catch (IOException e) {
GrailsCoreActivator.log(e);
}
}
protected FileSearcher createGSPSearcher(ISearchRequestor requestor, IFile gspFile) {
return null;
}
protected FileSearcher createURLMappingSearcher(ISearchRequestor requestor, IFile urlMappingsFile) {
return null;
}
protected abstract SearchingCodeVisitor createSearchingVisitor(ISearchRequestor requestor, ICompilationUnit cu);
/**
* Adds all controllers from a given JavaProject to the list of types to search in, but only if the types are
* included in the given search scope.
*/
public void addControllersFrom(IJavaProject project, IJavaSearchScope scope) {
PerProjectControllerCache controllerCache = GrailsCore.get().connect(project.getProject(), PerProjectControllerCache.class);
if (controllerCache != null) {
for (ControllerTarget controller : controllerCache.getAllControllerTargets()) {
try {
IType controllerClass = controller.toJavaElement();
if (encloses(scope, controllerClass)) {
add(controllerClass);
}
} catch (JavaModelException e) {
GrailsCoreActivator.log(e);
}
}
}
}
public void addUrlMappingsFrom(GrailsProject project, IJavaSearchScope scope) {
Assert.isLegal(urlMappingsToSearch==null); //Only expecting so search one file, so only have support to track one file and it can only be set once.
IFile file = project.getJavaProject().getProject().getFile(new Path("grails-app/conf/UrlMappings.groovy"));
if (file.exists() && encloses(scope, file)) {
urlMappingsToSearch = file;
}
}
public void addGspFilesFrom(GrailsProject project, IJavaSearchScope scope) {
//Note: better to ignore the scope, because it typically doesn't include
//the GSPfiles, but we do want to search them!
gspFilesToSearch.addAll(project.getGSPFiles());
}
private boolean encloses(IJavaSearchScope scope, IFile gspFile) {
if (scope!=null) {
return scope.encloses(gspFile.getFullPath().toString());
} else {
return true;
}
}
private boolean encloses(IJavaSearchScope scope, IType controllerClass) {
if (scope!=null) {
return scope.encloses(controllerClass);
}
return true;
}
}