/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.erlide.ui.internal.search;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.editors.text.TextEditor;
import org.erlide.core.services.search.SearchCoreUtil;
import org.erlide.engine.ErlangEngine;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.IErlElement;
import org.erlide.engine.model.erlang.IErlAttribute;
import org.erlide.engine.model.erlang.IErlFunctionClause;
import org.erlide.engine.model.erlang.IErlPreprocessorDef;
import org.erlide.engine.model.root.IErlModule;
import org.erlide.engine.services.search.ErlSearchScope;
import org.erlide.engine.services.search.ErlangSearchPattern;
import org.erlide.engine.services.search.LimitTo;
import org.erlide.engine.services.search.OpenResult;
import org.erlide.engine.services.search.OpenService;
import org.erlide.engine.services.search.SearchPatternFactory;
import org.erlide.ui.actions.SelectionDispatchAction;
import org.erlide.ui.editors.erl.AbstractErlangEditor;
import org.erlide.ui.internal.ExceptionHandler;
import org.erlide.util.ErlLogger;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* Abstract class for Erlang search actions.
* <p>
* Note: This class is for internal use only. Clients should not use this class.
* </p>
*
* @since 2.0
*/
public abstract class FindAction extends SelectionDispatchAction {
// A dummy which can't be selected in the UI
// private static final IErlElement RETURN_WITHOUT_BEEP = ErlangCore
// .create(ErlangPlugin.getWorkspace().getRoot());
private AbstractErlangEditor fEditor;
FindAction(final IWorkbenchSite site) {
super(site);
init();
}
FindAction(final AbstractErlangEditor editor) {
this(editor.getEditorSite());
fEditor = editor;
setEnabled(true); // FIXME check selection, steal stuff from 'open'
}
/**
* Called once by the constructors to initialize label, tooltip, image and
* help support of the action. To be overridden by implementors of this
* action.
*/
abstract void init();
private boolean canOperateOn(final IStructuredSelection sel) {
return sel != null && !sel.isEmpty() && canOperateOn(getErlElement(sel, true));
}
boolean canOperateOn(final IErlElement element) {
if (element instanceof IErlFunctionClause) {
return true;
} else if (element instanceof IErlPreprocessorDef) {
return true;
} else if (element instanceof IErlAttribute) {
final IErlAttribute a = (IErlAttribute) element;
return a.getName().startsWith("include");
}
return false;
}
// private IErlElement getTypeIfPossible(IErlElement o, final boolean
// silent) {
// switch (o.getElementType()) {
// case IErlElement.COMPILATION_UNIT:
// if (silent) {
// return o;
// } else {
// return findType((ICompilationUnit) o, silent);
// }
// case IErlElement.CLASS_FILE:
// return ((IClassFile) o).getType();
// default:
// return o;
// }
// }
IErlElement getErlElement(final IStructuredSelection selection, final boolean silent) {
if (selection.size() == 1) {
final Object firstElement = selection.getFirstElement();
if (firstElement instanceof IErlElement) {
return (IErlElement) firstElement;
} else if (firstElement instanceof IAdaptable) {
return (IErlElement) ((IAdaptable) firstElement)
.getAdapter(IErlElement.class);
}
}
return null;
}
private void showOperationUnavailableDialog() {
MessageDialog.openInformation(getShell(), "Operation unavailable",
getOperationUnavailableMessage());
}
String getOperationUnavailableMessage() {
return "Operation unavailable";
}
// private IErlElement findType(ICompilationUnit cu, final boolean silent)
// {
// IType[] types = null;
// try {
// types = cu.getAllTypes();
// } catch (JavaModelException ex) {
// if (JavaModelUtil.isExceptionToBeLogged(ex)) {
// ExceptionHandler.log(ex,
// SearchMessages.JavaElementAction_error_open_message);
// }
// if (silent) {
// return RETURN_WITHOUT_BEEP;
// } else {
// return null;
// }
// }
// if (types.length == 1 || silent && types.length > 0) {
// return types[0];
// }
// if (silent) {
// return RETURN_WITHOUT_BEEP;
// }
// if (types.length == 0) {
// return null;
// }
// final String title =
// SearchMessages.JavaElementAction_typeSelectionDialog_title;
// final String message =
// SearchMessages.JavaElementAction_typeSelectionDialog_message;
// final int flags = JavaElementLabelProvider.SHOW_DEFAULT;
//
// final ElementListSelectionDialog dialog = new ElementListSelectionDialog(
// getShell(), new JavaElementLabelProvider(flags));
// dialog.setTitle(title);
// dialog.setMessage(message);
// dialog.setElements(types);
//
// if (dialog.open() == Window.OK) {
// return (IType) dialog.getFirstResult();
// } else {
// return RETURN_WITHOUT_BEEP;
// }
// }
/*
* Method declared on SelectionChangedAction.
*/
@Override
public void run(final IStructuredSelection selection) {
final IErlElement element = getErlElement(selection, false);
if (element == null || !element.exists()) {
showOperationUnavailableDialog();
return;
}
// else if (element == RETURN_WITHOUT_BEEP) {
// return;
// }
run(element);
}
/*
* Method declared on SelectionChangedAction.
*/
@Override
public void run(final ITextSelection selection) {
try {
final IErlModule module = fEditor.getModule();
if (module == null) {
return;
}
final ISelection sel = getSelection();
final ITextSelection textSel = (ITextSelection) sel;
final int offset = textSel.getOffset();
final OpenResult res = ErlangEngine
.getInstance()
.getService(OpenService.class)
.open(module.getScannerName(),
offset,
ErlangEngine.getInstance().getModelUtilService()
.getImportsAsList(module), "",
ErlangEngine.getInstance().getModel().getPathVars());
ErlLogger.debug("find " + res);
final ErlangSearchPattern ref = SearchUtil
.getSearchPatternFromOpenResultAndLimitTo(module, offset, res,
getLimitTo(), true);
if (ref != null) {
SearchUtil.runQuery(ref, getScope(), getScopeDescription(), getShell());
}
} catch (final Exception e) {
handleException(e);
}
}
abstract LimitTo getLimitTo();
abstract protected ErlSearchScope getScope() throws ErlModelException, CoreException;
abstract protected String getScopeDescription();
/*
* Method declared on SelectionChangedAction.
*/
@Override
public void selectionChanged(final IStructuredSelection selection) {
setEnabled(canOperateOn(selection));
}
/*
* Method declared on SelectionChangedAction.
*/
@Override
public void selectionChanged(final ITextSelection selection) {
setEnabled(true);
}
/**
* Executes this action for the given java element.
*
* @param element
* The erlang element to be found.
* @throws CoreException
*/
public void run(final IErlElement element) {
try {
final ErlangSearchPattern pattern = new SearchPatternFactory(ErlangEngine
.getInstance().getModelUtilService())
.getSearchPatternFromErlElementAndLimitTo(element, getLimitTo());
SearchUtil.runQuery(pattern, getScope(), getScopeDescription(), getShell());
} catch (final CoreException e) {
handleException(e);
}
}
protected void handleException(final Exception e) {
ExceptionHandler.handle(new InvocationTargetException(e), getShell(), "Search",
"Problems occurred while searching. "
+ "The affected files will be skipped.");
}
/**
* @return the fEditor
*/
public AbstractErlangEditor getEditor() {
return fEditor;
}
protected Collection<IProject> getProjects() {
final TextEditor editor = getEditor();
if (editor != null) {
final IEditorInput editorInput = editor.getEditorInput();
if (editorInput instanceof IFileEditorInput) {
final IFileEditorInput input = (IFileEditorInput) editorInput;
final IFile file = input.getFile();
final IProject project = file.getProject();
return Lists.newArrayList(project);
}
} else {
final IWorkbenchSite site = getSite();
final ISelection selection = site.getSelectionProvider().getSelection();
if (selection instanceof IStructuredSelection) {
final IStructuredSelection ss = (IStructuredSelection) selection;
final Collection<IProject> result = Sets.newHashSet();
for (final Object element : ss.toList()) {
if (element instanceof IErlElement) {
final IErlElement e = (IErlElement) element;
result.add(e.getResource().getProject());
} else if (element instanceof IResource) {
final IResource r = (IResource) element;
result.add(r.getProject());
}
}
return result;
}
}
return null;
}
protected ErlSearchScope getProjectScope() throws CoreException {
return SearchCoreUtil.getProjectsScope(getProjects(), false, false);
}
}