// =====================================================================
//
// Copyright (C) 2012 - 2016, Philip Graf
//
// 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
//
// =====================================================================
package ch.acanda.eclipse.pmd.wizard;
import java.nio.file.Paths;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import ch.acanda.eclipse.pmd.PMDPlugin;
import ch.acanda.eclipse.pmd.domain.Location;
import ch.acanda.eclipse.pmd.domain.LocationContext;
import ch.acanda.eclipse.pmd.domain.RuleSetModel;
import ch.acanda.eclipse.pmd.ui.dialog.FileSelectionDialog;
import com.google.common.base.Optional;
/**
* Controller for the wizard to add a new rule set configuration.
*
* @author Philip Graf
*/
final class AddRuleSetConfigurationController {
private final AddRuleSetConfigurationModel model;
private final IProject project;
public AddRuleSetConfigurationController(final IProject project) {
model = new AddRuleSetConfigurationModel(project);
this.project = project;
}
public AddRuleSetConfigurationModel getModel() {
return model;
}
public void browse(final Shell shell) {
if (model.isFileSystemTypeSelected()) {
final FileDialog fileDialog = new FileDialog(shell);
final String file = fileDialog.open();
if (file != null) {
model.setLocation(file);
}
} else if (model.isProjectTypeSelected()) {
final Optional<IResource> resource = browseContainer(shell, project);
if (resource.isPresent()) {
model.setLocation(getRelativePath(project, resource.get()));
}
} else if (model.isWorkspaceTypeSelected()) {
final Optional<IResource> optionalResource = browseContainer(shell, project.getWorkspace().getRoot());
if (optionalResource.isPresent()) {
final IResource resource = optionalResource.get();
model.setLocation(resource.getProject().getName() + "/" + resource.getProjectRelativePath().toString());
}
} else {
throw new IllegalStateException();
}
}
private Optional<IResource> browseContainer(final Shell shell, final IContainer container) {
final FileSelectionDialog dialog = new FileSelectionDialog(shell);
dialog.setMessage("Choose a PMD rule set configuration:");
dialog.setValidator(new ISelectionStatusValidator() {
@Override
public IStatus validate(final Object[] selection) {
IStatus result = new Status(IStatus.OK, PMDPlugin.ID, "");
if (selection.length == 1 && !(selection[0] instanceof IContainer)) {
final IResource resource = (IResource) selection[0];
final String configuration = resource.getLocation().toOSString();
try {
new RuleSetFactory().createRuleSet(configuration);
} catch (final RuleSetNotFoundException | IllegalArgumentException e) {
// the rule set location is invalid
result = new Status(IStatus.WARNING, PMDPlugin.ID, resource.getName()
+ " is not a valid PMD rule set configuration");
}
} else {
result = new Status(IStatus.WARNING, PMDPlugin.ID, "");
}
return result;
}
});
dialog.setInput(container);
if (dialog.open() == Window.OK) {
return Optional.of((IResource) dialog.getFirstResult());
}
return Optional.absent();
}
private String getRelativePath(final IContainer container, final IResource resource) {
return Paths.get(container.getLocationURI()).relativize(Paths.get(resource.getLocationURI())).toString().replace('\\', '/');
}
public RuleSetModel createRuleSetModel() {
if (model.isValid()) {
return new RuleSetModel(model.getName(), new Location(model.getLocation(), getLocationContext()));
}
throw new IllegalStateException("Cannot create RuleSetModel as the view model is not valid");
}
private LocationContext getLocationContext() {
final LocationContext locationContext;
if (model.isWorkspaceTypeSelected()) {
locationContext = LocationContext.WORKSPACE;
} else if (model.isProjectTypeSelected()) {
locationContext = LocationContext.PROJECT;
} else if (model.isFileSystemTypeSelected()) {
locationContext = LocationContext.FILE_SYSTEM;
} else if (model.isRemoteTypeSelected()) {
locationContext = LocationContext.REMOTE;
} else {
throw new IllegalStateException("Unknown configuration type");
}
return locationContext;
}
}