blob: 81e996f28798246bf64d68a62e34c64baf568d74 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.wizards.buildpaths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.actions.AbstractOpenWizardAction;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
public class CreateMultipleSourceFoldersDialog extends TrayDialog {
private final class FakeFolderBaseWorkbenchContentProvider extends BaseWorkbenchContentProvider {
@Override
public Object getParent(Object element) {
Object object= fNonExistingFolders.get(element);
if (object != null)
return object;
return super.getParent(element);
}
@Override
public Object[] getChildren(Object element) {
List<Object> result= new ArrayList<>();
//all keys with value element
Set<IFolder> keys= fNonExistingFolders.keySet();
for (Iterator<IFolder> iter= keys.iterator(); iter.hasNext();) {
Object key= iter.next();
if (fNonExistingFolders.get(key).equals(element)) {
result.add(key);
}
}
if (result.size() == 0)
return super.getChildren(element);
Object[] children= super.getChildren(element);
result.addAll(Arrays.asList(children));
return result.toArray();
}
}
private final IJavaProject fJavaProject;
private final CPListElement[] fExistingElements;
private String fOutputLocation;
private final HashSet<CPListElement> fRemovedElements;
private final HashSet<CPListElement> fModifiedElements;
private final HashSet<CPListElement> fInsertedElements;
private final Hashtable<IFolder, IContainer> fNonExistingFolders;
public CreateMultipleSourceFoldersDialog(final IJavaProject javaProject, final CPListElement[] existingElements, final String outputLocation, Shell shell) {
super(shell);
fJavaProject= javaProject;
fExistingElements= existingElements;
fOutputLocation= outputLocation;
fRemovedElements= new HashSet<>();
fModifiedElements= new HashSet<>();
fInsertedElements= new HashSet<>();
fNonExistingFolders= new Hashtable<>();
for (int i= 0; i < existingElements.length; i++) {
CPListElement cur= existingElements[i];
if (cur.getResource() == null || !cur.getResource().exists()) {
addFakeFolder(fJavaProject.getProject(), cur);
}
}
}
@Override
public int open() {
Class<?>[] acceptedClasses= new Class<?>[] { IProject.class, IFolder.class };
List<IResource> existingContainers= getExistingContainers(fExistingElements);
IProject[] allProjects= ResourcesPlugin.getWorkspace().getRoot().getProjects();
ArrayList<IProject> rejectedElements= new ArrayList<>(allProjects.length);
IProject currProject= fJavaProject.getProject();
for (int i= 0; i < allProjects.length; i++) {
if (!allProjects[i].equals(currProject)) {
rejectedElements.add(allProjects[i]);
}
}
ViewerFilter filter= new TypedViewerFilter(acceptedClasses, rejectedElements.toArray()){
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IFolder && ((IFolder)element).isVirtual()) {
return false;
}
return super.select(viewer, parentElement, element);
}
};
ILabelProvider lp= new WorkbenchLabelProvider();
ITreeContentProvider cp= new FakeFolderBaseWorkbenchContentProvider();
String title= NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_new_title;
String message= NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_edit_description;
MultipleFolderSelectionDialog dialog= new MultipleFolderSelectionDialog(getShell(), lp, cp) {
@Override
protected Control createDialogArea(Composite parent) {
Control result= super.createDialogArea(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IJavaHelpContextIds.BP_CHOOSE_EXISTING_FOLDER_TO_MAKE_SOURCE_FOLDER);
return result;
}
@Override
protected Object createFolder(final IContainer container) {
final Object[] result= new Object[1];
final CPListElement newElement= new CPListElement(fJavaProject, IClasspathEntry.CPE_SOURCE);
final AddSourceFolderWizard wizard= newSourceFolderWizard(newElement, fExistingElements, fOutputLocation, container);
AbstractOpenWizardAction action= new AbstractOpenWizardAction() {
@Override
protected INewWizard createWizard() throws CoreException {
return wizard;
}
};
action.addPropertyChangeListener(new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(IAction.RESULT)) {
if (event.getNewValue().equals(Boolean.TRUE)) {
result[0]= addFakeFolder(fJavaProject.getProject(), newElement);
} else {
wizard.cancel();
}
}
}
});
action.run();
return result[0];
}
};
dialog.setExisting(existingContainers.toArray());
dialog.setTitle(title);
dialog.setMessage(message);
dialog.addFilter(filter);
dialog.setInput(fJavaProject.getProject().getParent());
dialog.setInitialFocus(fJavaProject.getProject());
if (dialog.open() == Window.OK) {
Object[] elements= dialog.getResult();
for (int i= 0; i < elements.length; i++) {
IResource res= (IResource)elements[i];
fInsertedElements.add(new CPListElement(fJavaProject, IClasspathEntry.CPE_SOURCE, res.getFullPath(), res));
}
if (fExistingElements.length == 1) {
CPListElement existingElement= fExistingElements[0];
if (existingElement.getResource() instanceof IProject) {
if (!removeProjectFromBP(existingElement)) {
ArrayList<CPListElement> added= new ArrayList<>(fInsertedElements);
HashSet<CPListElement> updatedEclusionPatterns= new HashSet<>();
addExlusionPatterns(added, updatedEclusionPatterns);
fModifiedElements.addAll(updatedEclusionPatterns);
}
}
} else {
ArrayList<CPListElement> added= new ArrayList<>(fInsertedElements);
HashSet<CPListElement> updatedEclusionPatterns= new HashSet<>();
addExlusionPatterns(added, updatedEclusionPatterns);
fModifiedElements.addAll(updatedEclusionPatterns);
}
return Window.OK;
} else {
return Window.CANCEL;
}
}
public List<CPListElement> getInsertedElements() {
return new ArrayList<>(fInsertedElements);
}
public List<CPListElement> getRemovedElements() {
return new ArrayList<>(fRemovedElements);
}
public List<CPListElement> getModifiedElements() {
return new ArrayList<>(fModifiedElements);
}
public IPath getOutputLocation() {
return new Path(fOutputLocation).makeAbsolute();
}
/**
* Asks to change the output folder to 'proj/bin' when no source folders were existing
*
* @param existing the element to remove
* @return returns <code>true</code> if the element has been removed
*/
private boolean removeProjectFromBP(CPListElement existing) {
IPath outputFolder= new Path(fOutputLocation);
IPath newOutputFolder= null;
String message;
if (outputFolder.segmentCount() == 1) {
String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
newOutputFolder= outputFolder.append(outputFolderName);
message= Messages.format(NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_and_output_message, BasicElementLabels.getPathLabel(newOutputFolder, false));
} else {
message= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_message;
}
String title= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_title;
if (MessageDialog.openQuestion(getShell(), title, message)) {
fRemovedElements.add(existing);
if (newOutputFolder != null) {
fOutputLocation= newOutputFolder.toString();
}
return true;
}
return false;
}
private void addExlusionPatterns(List<CPListElement> newEntries, Set<CPListElement> modifiedEntries) {
BuildPathBasePage.fixNestingConflicts(newEntries.toArray(new CPListElement[newEntries.size()]), fExistingElements, modifiedEntries);
if (!modifiedEntries.isEmpty()) {
String title= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_title;
String message= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_message;
MessageDialog.openInformation(getShell(), title, message);
}
}
private AddSourceFolderWizard newSourceFolderWizard(CPListElement element, CPListElement[] existing, String outputLocation, IContainer parent) {
AddSourceFolderWizard wizard= new AddSourceFolderWizard(existing, element, new Path(outputLocation).makeAbsolute(), false, true, false, false, false, parent);
wizard.setDoFlushChange(false);
return wizard;
}
private List<IResource> getExistingContainers(CPListElement[] existingElements) {
List<IResource> res= new ArrayList<>();
for (int i= 0; i < existingElements.length; i++) {
IResource resource= existingElements[i].getResource();
if (resource instanceof IContainer) {
res.add(resource);
}
}
Set<IFolder> keys= fNonExistingFolders.keySet();
for (Iterator<IFolder> iter= keys.iterator(); iter.hasNext();) {
IFolder folder= iter.next();
res.add(folder);
}
return res;
}
private IFolder addFakeFolder(final IContainer container, final CPListElement element) {
IFolder result;
IPath projectPath= fJavaProject.getPath();
IPath path= element.getPath();
if (projectPath.isPrefixOf(path)) {
path= path.removeFirstSegments(projectPath.segmentCount());
}
result= container.getFolder(path);
IFolder folder= result;
do {
IContainer parent= folder.getParent();
fNonExistingFolders.put(folder, parent);
if (parent instanceof IFolder) {
folder= (IFolder)parent;
} else {
folder= null;
}
} while (folder != null && !folder.exists());
return result;
}
}