blob: 2c3176eb1f00243230227a13c8811e2e93d2673a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007-2019 Cisco Systems, 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:
* E. Dillon (Cisco Systems, Inc.) - reformat for Code Open-Sourcing
*******************************************************************************/
package org.eclipse.tigerstripe.workbench.ui.internal.dialogs;
import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.tigerstripe.workbench.TigerstripeException;
import org.eclipse.tigerstripe.workbench.internal.BasePlugin;
import org.eclipse.tigerstripe.workbench.internal.core.module.InstalledModule;
import org.eclipse.tigerstripe.workbench.internal.core.module.InstalledModuleManager;
import org.eclipse.tigerstripe.workbench.project.IDependency;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProjectInternal;
import org.eclipse.tigerstripe.workbench.ui.EclipsePlugin;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies.DependenciesImageProvider;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies.DependenciesSorter;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies.DependencyKind;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies.IDependencyKindResolver;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies.ITextProvider;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
/**
* Presents the user with a filterable list of Tigerstripe projects for
* selection
*
* @author Eric Dillon
*
*/
public class TigerstripeProjectSelectionDialog extends SelectionStatusDialog implements IProjectSelectionDialog {
// sizing constants
private static final int SIZING_SELECTION_WIDGET_HEIGHT = 250;
private static final int SIZING_SELECTION_WIDGET_WIDTH = 300;
private static final Set<String> DEPENDENCIES_EXTENSIONS = new HashSet<>(asList("jar", "zip"));
// the visual selection widget group
private TableViewer fTableViewer;
private Set<String> fFilteredOutProjects;
private ViewerFilter fFilter;
private final ITigerstripeModelProject currentProject;
private static final IDependencyKindResolver KIND_RESOLVER = obj -> {
if (obj instanceof IJavaProject) {
return DependencyKind.PROJECT;
} else if (obj instanceof InstalledModule) {
return DependencyKind.MODULE;
} else if (obj instanceof IResource) {
return DependencyKind.DEPENDENCY;
} else {
return DependencyKind.UNKNOWN;
}
};
class TigerstripeProjectReferencesProvider extends StandardJavaElementContentProvider {
@Override
public Object[] getElements(Object parent) {
Map<String, Object> projsAndModulesMap = new HashMap<>();
Object[] javaResult = super.getElements(parent);
InstalledModule[] modules = InstalledModuleManager.getInstance().getModules();
Collection<Object> projsAndModules = new ArrayList<>();
projsAndModules.addAll(asList(javaResult));
projsAndModules.addAll(asList(modules));
for (Object o : projsAndModules) {
String id;
if (o instanceof IJavaProject) {
IJavaProject javaProject = (IJavaProject) o;
ITigerstripeModelProject tsp = javaProject.getAdapter(ITigerstripeModelProject.class);
if (tsp != null) {
try {
id = tsp.getModelId();
} catch (TigerstripeException e) {
BasePlugin.log(e);
continue;
}
} else {
continue;
}
} else if (o instanceof InstalledModule) {
InstalledModule module = (InstalledModule) o;
id = module.getModuleID();
} else {
continue;
}
if (!projsAndModulesMap.containsKey(id)) {
projsAndModulesMap.put(id, o);
}
}
Collection<IResource> dependencies = findDependencies();
Set<Object> all = new HashSet<>(projsAndModulesMap.size() + dependencies.size());
all.addAll(projsAndModulesMap.values());
all.addAll(dependencies);
return all.toArray(new Object[0]);
}
}
private Collection<IResource> findDependencies() {
IProject project = ((ITigerstripeModelProjectInternal) currentProject).getAdapter(IProject.class);
// Need to be careful that we don;t pick up anything that is in the
// target directory as a potential dependency.
IContainer targetFolder = null;
try {
IPath output = new Path(currentProject.getProjectDetails().getOutputDirectory());
if (output.segmentCount() > 1) {
output = output.removeLastSegments(output.segmentCount() - 1);
}
IResource res = project.findMember(output);
if (res instanceof IContainer) {
targetFolder = (IContainer) res;
}
} catch (TigerstripeException e1) {
// ignore
}
final Collection<IResource> result = new HashSet<>();
final IContainer targetContainer = targetFolder;
try {
project.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
if (resource.getParent().equals(targetContainer)) {
return false;
}
if (resource instanceof IFile) {
if (DEPENDENCIES_EXTENSIONS.contains(resource.getFileExtension())) {
result.add(resource);
}
return false;
}
return true;
}
});
} catch (CoreException e) {
EclipsePlugin.log(e);
}
return result;
}
static class TigerstripeProjectReferencesLabelProvider extends JavaElementLabelProvider {
private final DependenciesImageProvider imageProvider = new DependenciesImageProvider(KIND_RESOLVER);
public TigerstripeProjectReferencesLabelProvider() {
super(SHOW_PARAMETERS | SHOW_SMALL_ICONS);
}
@Override
public String getText(Object element) {
if (element instanceof InstalledModule) {
InstalledModule module = (InstalledModule) element;
StringBuilder buffer = new StringBuilder();
buffer.append(module.getModuleID());
String version = module.getModule().getProjectDetails().getVersion();
if (version != null && version.length() > 0) {
buffer.append(" (");
buffer.append(version);
buffer.append(")");
}
return buffer.toString();
} else if (element instanceof IResource) {
return ((IResource) element).getName();
} else {
return super.getText(element);
}
}
@Override
public Image getImage(Object element) {
return imageProvider.getImage(element);
}
}
public TigerstripeProjectSelectionDialog(Shell parentShell, Set<String> filteredOutProjects,
final ITigerstripeModelProjectInternal currentProject) {
super(parentShell);
this.currentProject = currentProject;
setTitle("Select Tigerstripe Project");
setMessage("Select Tigerstripe Project to reference");
fFilteredOutProjects = filteredOutProjects;
int shellStyle = getShellStyle();
setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
fFilter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IJavaProject) {
IJavaProject prj = (IJavaProject) element;
ITigerstripeModelProject tsProject = prj.getProject().getAdapter(ITigerstripeModelProject.class);
if (tsProject != null && tsProject.exists()) {
try {
return fFilteredOutProjects.contains(tsProject.getModelId());
} catch (TigerstripeException e) {
// Ignore
}
}
return false;
} else if (element instanceof InstalledModule) {
return fFilteredOutProjects.contains(((InstalledModule) element).getModuleID());
} else if (element instanceof IResource) {
try {
IDependency[] dependencies = currentProject.getDependencies();
for (IDependency dep : dependencies) {
if (dep.getPath().equals(((IResource) element).getProjectRelativePath().toOSString())) {
return false;
}
}
return true;
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
return false;
}
} else {
return false;
}
}
};
}
/*
* (non-Javadoc) Method declared on Dialog.
*/
@Override
protected Control createDialogArea(Composite parent) {
// page group
Composite composite = (Composite) super.createDialogArea(parent);
Font font = parent.getFont();
composite.setFont(font);
createMessageArea(composite);
fTableViewer = new TableViewer(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.MULTI);
fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
doSelectionChanged(((IStructuredSelection) event.getSelection()).toArray());
}
});
fTableViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
okPressed();
}
});
fTableViewer.addFilter(fFilter);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.heightHint = SIZING_SELECTION_WIDGET_HEIGHT;
data.widthHint = SIZING_SELECTION_WIDGET_WIDTH;
fTableViewer.getTable().setLayoutData(data);
final TigerstripeProjectReferencesLabelProvider labelProvider = new TigerstripeProjectReferencesLabelProvider();
fTableViewer.setLabelProvider(labelProvider);
fTableViewer.setContentProvider(new TigerstripeProjectReferencesProvider());
ITextProvider textAdapter = new ITextProvider() {
public String getText(Object obj) {
return labelProvider.getText(obj);
}
};
fTableViewer.setComparator(new DependenciesSorter(textAdapter, KIND_RESOLVER));
fTableViewer.getControl().setFont(font);
final Button checkbox = new Button(composite, SWT.CHECK);
checkbox.setText("Add Transitive dependencies");
checkbox.setSelection(isIncludeTransitiveDependencies());
checkbox.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
checkbox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setIncludeTransitiveDependencies(checkbox.getSelection());
}
});
IJavaModel input = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
fTableViewer.setInput(input);
doSelectionChanged(new Object[0]);
Dialog.applyDialogFont(composite);
return composite;
}
private boolean includeTransitive = false;
public boolean isIncludeTransitiveDependencies() {
return includeTransitive;
}
private void setIncludeTransitiveDependencies(boolean b) {
includeTransitive = b;
}
private void doSelectionChanged(Object[] objects) {
if (objects.length == 0) {
updateStatus(new StatusInfo(IStatus.ERROR, "")); //$NON-NLS-1$
setSelectionResult(null);
} else {
updateStatus(new StatusInfo());
setSelectionResult(objects);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
*/
@Override
protected void computeResult() {
}
}