/*
* Copyright 2015 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.project.editor.libraries;
import static com.google.common.collect.Lists.newArrayList;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.statushandlers.StatusManager;
import org.rf.ide.core.executor.RobotRuntimeEnvironment;
import org.rf.ide.core.executor.RobotRuntimeEnvironment.RobotEnvironmentException;
import org.rf.ide.core.project.RobotProjectConfig;
import org.rf.ide.core.project.RobotProjectConfig.LibraryType;
import org.rf.ide.core.project.RobotProjectConfig.ReferencedLibrary;
import org.robotframework.ide.eclipse.main.plugin.RedImages;
import org.robotframework.ide.eclipse.main.plugin.RedPlugin;
import org.robotframework.ide.eclipse.main.plugin.RedWorkspace;
import org.robotframework.ide.eclipse.main.plugin.project.editor.libraries.JarStructureBuilder.JarClass;
import org.robotframework.ide.eclipse.main.plugin.project.editor.libraries.PythonLibStructureBuilder.PythonClass;
import org.robotframework.red.graphics.ImagesManager;
import org.robotframework.red.jface.dialogs.DetailedErrorDialog;
/**
* @author Michal Anglart
*/
public class ReferencedLibraryImporter {
public Collection<ReferencedLibrary> importPythonLib(final Shell shellForDialogs,
final RobotRuntimeEnvironment environment, final IProject project, final RobotProjectConfig config,
final String fullLibraryPath) {
final PythonLibStructureBuilder pythonLibStructureBuilder = new PythonLibStructureBuilder(environment, config,
project);
final List<ILibraryClass> pythonClasses = newArrayList();
try {
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Reading classes/modules from module '" + fullLibraryPath + "'", 100);
try {
pythonClasses.addAll(pythonLibStructureBuilder.provideEntriesFromFile(fullLibraryPath));
} catch (final RobotEnvironmentException e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
DetailedErrorDialog.openErrorDialog(
"RED was unable to find classes/modules inside '" + fullLibraryPath + "' module",
e.getCause().getMessage());
return new ArrayList<>();
}
if (pythonClasses.isEmpty()) {
StatusManager.getManager()
.handle(new Status(IStatus.ERROR, RedPlugin.PLUGIN_ID,
"RED was unable to find classes/modules inside '" + fullLibraryPath + "' module"),
StatusManager.SHOW);
return new ArrayList<>();
} else if (pythonClasses.size() == 1) {
return newArrayList(pythonClasses.get(0).toReferencedLibrary(fullLibraryPath));
} else {
final ElementListSelectionDialog classesDialog = createSelectionDialog(shellForDialogs, fullLibraryPath,
pythonClasses, new PythonClassesLabelProvider());
if (classesDialog.open() == Window.OK) {
final Object[] result = classesDialog.getResult();
final Collection<ReferencedLibrary> libraries = new ArrayList<>();
for (final Object selectedClass : result) {
final PythonClass pythonClass = (PythonClass) selectedClass;
libraries.add(pythonClass.toReferencedLibrary(fullLibraryPath));
}
return libraries;
}
return new ArrayList<>();
}
}
public Collection<ReferencedLibrary> importJavaLib(final Shell shell, final RobotRuntimeEnvironment environment,
final IProject project, final RobotProjectConfig config, final String fullLibraryPath) {
final JarStructureBuilder jarStructureBuilder = new JarStructureBuilder(environment, config, project);
final List<ILibraryClass> classesFromJar = newArrayList();
try {
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Reading classes from module '" + fullLibraryPath + "'", 100);
classesFromJar.addAll(jarStructureBuilder.provideEntriesFromFile(fullLibraryPath));
}
});
} catch (InvocationTargetException | InterruptedException e) {
StatusManager.getManager()
.handle(new Status(IStatus.ERROR, RedPlugin.PLUGIN_ID,
"RED was unable to find classes inside '" + fullLibraryPath + "' module", e.getCause()),
StatusManager.SHOW);
return new ArrayList<>();
}
if (classesFromJar.isEmpty()) {
StatusManager.getManager()
.handle(new Status(IStatus.ERROR, RedPlugin.PLUGIN_ID,
"RED was unable to find classes inside '" + fullLibraryPath + "' module"),
StatusManager.SHOW);
return new ArrayList<>();
} else if (classesFromJar.size() == 1) {
return newArrayList(classesFromJar.get(0).toReferencedLibrary(fullLibraryPath));
} else {
final ElementListSelectionDialog classesDialog = createSelectionDialog(shell, fullLibraryPath,
classesFromJar, new JarClassesLabelProvider());
if (classesDialog.open() == Window.OK) {
final Object[] result = classesDialog.getResult();
final Collection<ReferencedLibrary> libraries = new ArrayList<>();
for (final Object selectedClass : result) {
final JarClass jarClass = (JarClass) selectedClass;
libraries.add(jarClass.toReferencedLibrary(fullLibraryPath));
}
return libraries;
}
return new ArrayList<>();
}
}
public ReferencedLibrary importLibFromSpecFile(final String fullLibraryPath) {
final IPath path = RedWorkspace.Paths.toWorkspaceRelativeIfPossible(new Path(fullLibraryPath));
return ReferencedLibrary.create(LibraryType.VIRTUAL, path.lastSegment(), path.toPortableString());
}
static ElementListSelectionDialog createSelectionDialog(final Shell shell, final String path, final List<?> classes,
final LabelProvider labelProvider) {
final ElementListSelectionDialog classesDialog = new ElementListSelectionDialog(shell, labelProvider);
classesDialog.setMultipleSelection(true);
classesDialog.setTitle("Select library class");
classesDialog.setMessage("Select the class(es) which defines library:\n\t" + path);
classesDialog.setElements(classes.toArray());
return classesDialog;
}
private static class PythonClassesLabelProvider extends LabelProvider {
@Override
public Image getImage(final Object element) {
return ImagesManager.getImage(RedImages.getJavaClassImage());
}
@Override
public String getText(final Object element) {
return ((PythonClass) element).getQualifiedName();
}
}
private static class JarClassesLabelProvider extends LabelProvider {
@Override
public Image getImage(final Object element) {
return ImagesManager.getImage(RedImages.getJavaClassImage());
}
@Override
public String getText(final Object element) {
return ((JarClass) element).getQualifiedName();
}
}
}