/*
* Copyright 2016 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.tableeditor;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IExecutionListener;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.rf.ide.core.project.RobotProjectConfig;
import org.rf.ide.core.testdata.model.table.setting.LibraryImport;
import org.rf.ide.core.validation.ProblemPosition;
import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordCall;
import org.robotframework.ide.eclipse.main.plugin.model.RobotProject;
import org.robotframework.ide.eclipse.main.plugin.model.RobotSettingsSection;
import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile;
import org.robotframework.ide.eclipse.main.plugin.project.LibrariesAutoDiscoverer;
import org.robotframework.ide.eclipse.main.plugin.project.build.BuildLogger;
import org.robotframework.ide.eclipse.main.plugin.project.build.ProblemsReportingStrategy;
import org.robotframework.ide.eclipse.main.plugin.project.build.RobotProblem;
import org.robotframework.ide.eclipse.main.plugin.project.build.causes.GeneralSettingsProblem;
import org.robotframework.ide.eclipse.main.plugin.project.build.validation.FileValidationContext;
import org.robotframework.ide.eclipse.main.plugin.project.build.validation.GeneralSettingsLibrariesImportValidator;
import org.robotframework.ide.eclipse.main.plugin.project.build.validation.ValidationContext;
import com.google.common.base.Function;
class OnSaveLibrariesAutodiscoveryTrigger implements IExecutionListener {
static final String SAVE_ALL_COMMAND_ID = "org.eclipse.ui.file.saveAll";
private static OnSaveLibrariesAutodiscoveryTrigger globalBatchSaveResponsibleTrigger = null;
private static final List<RobotSuiteFile> suitesForDiscover = new ArrayList<>();
private final DiscovererFactory discovererFactory;
OnSaveLibrariesAutodiscoveryTrigger() {
this(new DiscovererFactory() {
@Override
public LibrariesAutoDiscoverer create(final RobotProject robotProject, final List<IFile> suites) {
final boolean showSummary = robotProject.getRobotProjectConfig()
.isLibrariesAutoDiscoveringSummaryWindowEnabled();
return new LibrariesAutoDiscoverer(robotProject, suites, showSummary);
}
});
}
OnSaveLibrariesAutodiscoveryTrigger(final DiscovererFactory discovererFactory) {
this.discovererFactory = discovererFactory;
}
@Override
public void preExecute(final String commandId, final ExecutionEvent event) {
if (globalBatchSaveResponsibleTrigger == null && SAVE_ALL_COMMAND_ID.equals(commandId)) {
globalBatchSaveResponsibleTrigger = this;
}
}
@Override
public void notHandled(final String commandId, final NotHandledException exception) {
if (SAVE_ALL_COMMAND_ID.equals(commandId)) {
globalBatchSaveResponsibleTrigger = null;
suitesForDiscover.clear();
}
}
@Override
public void postExecuteFailure(final String commandId, final ExecutionException exception) {
if (SAVE_ALL_COMMAND_ID.equals(commandId)) {
globalBatchSaveResponsibleTrigger = null;
suitesForDiscover.clear();
}
}
@Override
public void postExecuteSuccess(final String commandId, final Object returnValue) {
if (globalBatchSaveResponsibleTrigger == this && SAVE_ALL_COMMAND_ID.equals(commandId)) {
globalBatchSaveResponsibleTrigger = null;
if (!suitesForDiscover.isEmpty()) {
final RobotProject project = suitesForDiscover.get(0).getProject();
startAutoDiscovering(project,
newArrayList(transform(suitesForDiscover, new Function<RobotSuiteFile, IFile>() {
@Override
public IFile apply(final RobotSuiteFile suite) {
return suite.getFile();
}
})));
}
suitesForDiscover.clear();
}
}
void startLibrariesAutoDiscoveryIfRequired(final RobotSuiteFile suite) {
if (shouldStartAutoDiscovering(suite)) {
if (globalBatchSaveResponsibleTrigger == null) {
startAutoDiscovering(suite.getProject(), newArrayList(suite.getFile()));
} else {
suitesForDiscover.add(suite);
}
}
}
private void startAutoDiscovering(final RobotProject robotProject, final List<IFile> suites) {
discovererFactory.create(robotProject, suites).start();
}
private boolean shouldStartAutoDiscovering(final RobotSuiteFile suite) {
final RobotProjectConfig projectConfig = suite.getProject().getRobotProjectConfig();
final boolean isAutodiscoveryEnabled = projectConfig != null
&& projectConfig.isReferencedLibrariesAutoDiscoveringEnabled();
return isAutodiscoveryEnabled && currentModelHaveUnknownLibrary(suite);
}
private boolean currentModelHaveUnknownLibrary(final RobotSuiteFile suite) {
final List<LibraryImport> imports = collectLibraryImports(suite);
final UnknownLibraryDetectingReportingStrategy reporter = new UnknownLibraryDetectingReportingStrategy();
final ValidationContext generalContext = new ValidationContext(suite.getProject(),
new BuildLogger());
final FileValidationContext fileContext = new FileValidationContext(generalContext, suite.getFile());
final GeneralSettingsLibrariesImportValidator importsValidator = new GeneralSettingsLibrariesImportValidator(
fileContext, suite, imports, reporter);
try {
importsValidator.validate(new NullProgressMonitor());
return reporter.unknownLibraryWasDetected();
} catch (final CoreException e) {
return false;
}
}
private List<LibraryImport> collectLibraryImports(final RobotSuiteFile currentModel) {
final List<LibraryImport> imports = new ArrayList<>();
final Optional<RobotSettingsSection> settingsSection = currentModel.findSection(RobotSettingsSection.class);
if (settingsSection.isPresent()) {
for (final RobotKeywordCall setting : settingsSection.get().getLibrariesSettings()) {
imports.add((LibraryImport) setting.getLinkedElement());
}
}
return imports;
}
private static class UnknownLibraryDetectingReportingStrategy extends ProblemsReportingStrategy {
private boolean detectedLibraryProblem = false;
UnknownLibraryDetectingReportingStrategy() {
super(false);
}
@Override
public void handleProblem(final RobotProblem problem, final IFile file, final ProblemPosition filePosition,
final Map<String, Object> additionalAttributes) {
if (problem.getCause() == GeneralSettingsProblem.NON_EXISTING_LIBRARY_IMPORT) {
this.detectedLibraryProblem = true;
}
}
boolean unknownLibraryWasDetected() {
return detectedLibraryProblem;
}
}
public interface DiscovererFactory {
LibrariesAutoDiscoverer create(RobotProject project, List<IFile> suites);
}
}