blob: 16e63f0905a15a49e2d08d71881e5855380c76a1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.search.internal.ui.text;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.widgets.Item;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.search.ui.text.AbstractTextSearchResult;
import org.eclipse.search.ui.text.Match;
import org.eclipse.search.internal.ui.SearchMessages;
import org.eclipse.search.internal.ui.SearchPlugin;
import org.eclipse.search.internal.ui.util.ExceptionHandler;
/* package */ class ReplaceAction2 extends Action {
private IWorkbenchSite fSite;
private IFile[] fElements;
private FileSearchPage fPage;
private static class ItemIterator implements Iterator {
private Item[] fArray;
private int fNextPosition;
ItemIterator(Item[] array) {
fArray= array;
fNextPosition= 0;
}
public boolean hasNext() {
return fNextPosition < fArray.length;
}
public Object next() {
if (!hasNext())
throw new NoSuchElementException();
return fArray[fNextPosition++].getData();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public ReplaceAction2(FileSearchPage page, IFile[] elements) {
Assert.isNotNull(page);
fSite= page.getSite();
if (elements != null)
fElements= elements;
else
fElements= new IFile[0];
fPage= page;
setText(SearchMessages.getString("ReplaceAction.label_all")); //$NON-NLS-1$
setEnabled(!(fElements.length == 0));
}
public ReplaceAction2(FileSearchPage page) {
Assert.isNotNull(page);
fSite= page.getSite();
fPage= page;
Item[] items= null;
StructuredViewer viewer= fPage.getViewer();
if (viewer instanceof TreeViewer) {
items= ((TreeViewer)viewer).getTree().getItems();
} else if (viewer instanceof TableViewer) {
items= ((TableViewer)viewer).getTable().getItems();
}
fElements= collectFiles(new ItemIterator(items));
setText(SearchMessages.getString("ReplaceAction.label_all")); //$NON-NLS-1$
setEnabled(!(fElements.length == 0));
}
public ReplaceAction2(FileSearchPage page, IStructuredSelection selection) {
fSite= page.getSite();
fPage= page;
setText(SearchMessages.getString("ReplaceAction.label_selected")); //$NON-NLS-1$
fElements= collectFiles(selection.iterator());
setEnabled(!(fElements.length == 0));
}
private IFile[] collectFiles(Iterator resources) {
final Set files= new HashSet();
while (resources.hasNext()) {
IResource resource= (IResource) resources.next();
try {
resource.accept(new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
if (proxy.getType() == IResource.FILE) {
files.add(proxy.requestResource());
return false;
}
return true;
}
}, IContainer.NONE);
} catch (CoreException e) {
// TODO Don't know yet how to handle this. This is called when we open the context
// menu. A bad time to show a dialog.
SearchPlugin.getDefault().getLog().log(e.getStatus());
}
}
return (IFile[]) files.toArray(new IFile[files.size()]);
}
private AbstractTextSearchResult getResult() {
return fPage.getInput();
}
public void run() {
if (validateResources((FileSearchQuery) getResult().getQuery())) {
ReplaceDialog2 dialog= new ReplaceDialog2(fSite.getShell(), fElements, fPage.getViewer(), getResult());
dialog.open();
}
}
private boolean validateResources(final FileSearchQuery operation) {
final List outOfDateEntries= new ArrayList();
for (int j= 0; j < fElements.length; j++) {
IFile entry = fElements[j];
Match[] markers= getResult().getMatches(entry);
for (int i= 0; i < markers.length; i++) {
if (isOutOfDate((FileMatch)markers[i])) {
outOfDateEntries.add(entry);
break;
}
}
}
final List outOfSyncEntries= new ArrayList();
for (int i= 0; i < fElements.length; i++) {
IFile entry = fElements[i];
if (isOutOfSync(entry)) {
outOfSyncEntries.add(entry);
}
}
if (outOfDateEntries.size() > 0 || outOfSyncEntries.size() > 0) {
if (askForResearch(outOfDateEntries, outOfSyncEntries)) {
ProgressMonitorDialog pmd= new ProgressMonitorDialog(fSite.getShell());
try {
pmd.run(true, true, new WorkspaceModifyOperation(null) {
protected void execute(IProgressMonitor monitor) throws CoreException {
research(monitor, outOfDateEntries, operation);
}
});
return true;
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, fSite.getShell(), SearchMessages.getString("ReplaceAction.label"), SearchMessages.getString("ReplaceAction.research.error")); //$NON-NLS-1$ //$NON-NLS-2$
} catch (InterruptedException e) {
// canceled
}
}
return false;
}
return true;
}
private void research(IProgressMonitor monitor, List outOfDateEntries, FileSearchQuery operation) throws CoreException {
IStatus status= null;
for (Iterator elements = outOfDateEntries.iterator(); elements.hasNext();) {
IFile entry = (IFile) elements.next();
status = research(operation, monitor, entry);
if (status != null && !status.isOK()) {
throw new CoreException(status);
}
}
}
private boolean askForResearch(List outOfDateEntries, List outOfSyncEntries) {
SearchAgainConfirmationDialog dialog= new SearchAgainConfirmationDialog(fSite.getShell(), (ILabelProvider) fPage.getViewer().getLabelProvider(), outOfSyncEntries, outOfDateEntries);
return dialog.open() == IDialogConstants.OK_ID;
}
private boolean isOutOfDate(FileMatch match) {
if (match.getCreationTimeStamp() != match.getFile().getModificationStamp())
return true;
ITextFileBufferManager bm= FileBuffers.getTextFileBufferManager();
ITextFileBuffer fb= bm.getTextFileBuffer(match.getFile().getFullPath());
if (fb != null && fb.isDirty())
return true;
return false;
}
private boolean isOutOfSync(IFile entry) {
return !entry.isSynchronized(IResource.DEPTH_ZERO);
}
private IStatus research(FileSearchQuery operation, final IProgressMonitor monitor, IFile entry) {
Match[] matches= getResult().getMatches(entry);
IStatus status= operation.searchInFile(getResult(), monitor, entry);
if (status == null || status.isOK()) {
for (int i= 0; i < matches.length; i++) {
getResult().removeMatch(matches[i]);
}
}
return status;
}
}