/**
* CertWare Project
* Copyright (c) 2010 National Aeronautics and Space Administration. All rights reserved.
* Original source from IBM data transfer internal package
*/
package net.certware.export.wizards;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import net.certware.core.ui.log.CertWareLog;
import net.certware.export.jobs.ExportResourceOperation;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.dialogs.WizardExportResourcesPage;
/**
* Wizard page for selecting source files for export to destination file.
* This class differs from its original data transfer internal class by the operation applied to the selections.
* @author mrb
*/
public class ExportSummaryPage extends WizardExportResourcesPage implements Listener { // $codepro.audit.disable declareDefaultConstructors
/** destination name field widget */
private Combo destinationNameField;
/** destination browse button widget */
private Button destinationBrowseButton;
/** overwrite existing files check box widget */
protected Button overwriteExistingFilesCheckbox;
/** create directory structure button widget */
protected Button createDirectoryStructureButton;
/** create selection only button widget */
protected Button createSelectionOnlyButton;
/** store key for destination names */
private static final String STORE_DESTINATION_NAMES_ID = "ExportSummaryPage.STORE_DESTINATION_NAMES_ID"; //$NON-NLS-1$
/** store key for overwrite exiting files */
private static final String STORE_OVERWRITE_EXISTING_FILES_ID = "ExportSummaryPage.STORE_OVERWRITE_EXISTING_FILES_ID"; //$NON-NLS-1$
/** store key for create structure */
private static final String STORE_CREATE_STRUCTURE_ID = "ExportSummaryPage.STORE_CREATE_STRUCTURE_ID"; //$NON-NLS-1$
/** select destination message */
private static final String SELECT_DESTINATION_MESSAGE = "Select destination";
/** dialog title for destination message */
private static final String SELECT_DESTINATION_TITLE = "Select Destination";
/** empty directory names list */
private static final String[] EMPTY_DIRECTORY_NAMES = new String[0];
/**
* Create an instance of this class.
* @param name wizard name
* @param selection selection for wizard reference
*/
protected ExportSummaryPage(String name, IStructuredSelection selection) {
super(name, selection);
}
/**
* Create an instance of this class.
* @param selection selection for wizard reference
*/
public ExportSummaryPage(IStructuredSelection selection) {
this("fileSystemExportPage1", selection); //$NON-NLS-1$
setTitle("Export to Document");
setDescription("Translates the results file to a document file in the local file system.");
}
/**
* Add the passed value to self's destination widget's history
* @param value destination name
*/
protected void addDestinationItem(String value) {
destinationNameField.add(value);
}
/**
* Create the control for the page.
* Calls super class then gives focus to the destination.
* Method declared on IDialogPage.
* @param parent control parent
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(Composite) */
public void createControl(Composite parent) {
super.createControl(parent);
giveFocusToDestination();
/*
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
IDataTransferHelpContextIds.FILE_SYSTEM_EXPORT_WIZARD_PAGE);
*/
}
/**
* Create the export destination specification widgets
* @param parent destination parent
*/
protected void createDestinationGroup(Composite parent) {
final Font font = parent.getFont();
// destination specification group
final Composite destinationSelectionGroup = new Composite(parent, SWT.NONE);
final GridLayout layout = new GridLayout();
layout.numColumns = 3; // $codepro.audit.disable numericLiterals
destinationSelectionGroup.setLayout(layout);
destinationSelectionGroup.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
destinationSelectionGroup.setFont(font);
final Label destinationLabel = new Label(destinationSelectionGroup, SWT.NONE);
destinationLabel.setText(getDestinationLabel());
destinationLabel.setFont(font);
// destination name entry field
destinationNameField = new Combo(destinationSelectionGroup, SWT.SINGLE | SWT.BORDER);
destinationNameField.addListener(SWT.Modify, this);
destinationNameField.addListener(SWT.Selection, this);
final GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
data.widthHint = SIZING_TEXT_FIELD_WIDTH;
destinationNameField.setLayoutData(data);
destinationNameField.setFont(font);
// destination browse button
destinationBrowseButton = new Button(destinationSelectionGroup, SWT.PUSH);
destinationBrowseButton.setText("Browse...");
destinationBrowseButton.addListener(SWT.Selection, this);
destinationBrowseButton.setFont(font);
setButtonLayoutData(destinationBrowseButton);
new Label(parent, SWT.NONE); // vertical spacer
}
/**
* Create the buttons in the options group.
* @param optionsGroup Group
*/
protected void createOptionsGroupButtons(Group optionsGroup) {
final Font font = optionsGroup.getFont();
createOverwriteExisting(optionsGroup, font);
createDirectoryStructureOptions(optionsGroup, font);
}
/**
* Create the buttons for the group that determine if the entire or
* selected directory structure should be created.
* @param optionsGroup group for related options
* @param font text font for buttons
*/
protected void createDirectoryStructureOptions(Composite optionsGroup, Font font) {
// create directory structure radios
createDirectoryStructureButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
createDirectoryStructureButton.setText("Create directory structure");
createDirectoryStructureButton.setSelection(false);
createDirectoryStructureButton.setFont(font);
// create directory structure radios
createSelectionOnlyButton = new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
createSelectionOnlyButton.setText("Create selected directories");
createSelectionOnlyButton.setSelection(true);
createSelectionOnlyButton.setFont(font);
}
/**
* Create the button for checking if we should ask if we are going to
* overwrite existing files.
* @param optionsGroup group for related options
* @param font buttons text font
*/
protected void createOverwriteExisting(Group optionsGroup, Font font) {
// overwrite... check box
overwriteExistingFilesCheckbox = new Button(optionsGroup, SWT.CHECK | SWT.LEFT);
overwriteExistingFilesCheckbox.setText("Overwrite existing files");
overwriteExistingFilesCheckbox.setFont(font);
}
/**
* Attempts to ensure that the specified directory exists on the local file system.
* Answers a boolean indicating success.
* @param directory directory to confirm
* @return true if directory exists, or does not exist and user chooses to create it */
protected boolean isExistingDirectory(File directory) {
if (!directory.exists()) {
if (!queryYesNoQuestion("Create target directory?")) {
return false;
}
if (!directory.mkdirs()) {
displayErrorDialog("Error creating directory");
giveFocusToDestination();
return false;
}
}
return true;
}
/**
* If the target for export does not exist then attempt to create it.
* Answer a boolean indicating whether the target exists (i.e.- if it either already exists
* or this method was able to create it).
*
* @param targetDirectory File
@return false if target is invalid or does not exist, true otherwise */
protected boolean isValidTarget(File targetDirectory) {
if (targetDirectory.exists() && !targetDirectory.isDirectory()) {
displayErrorDialog("Target is invalid");
giveFocusToDestination();
return false;
}
return isExistingDirectory(targetDirectory);
}
/**
* Set up and execute the passed Operation. Answer a boolean indicating success.
* @param op operation to perform for export
*
@return true if successful */
protected boolean canExportOperation(ExportResourceOperation op) {
op.setCreateLeadupStructure(createDirectoryStructureButton.getSelection());
op.setOverwriteFiles(overwriteExistingFilesCheckbox.getSelection());
try {
getContainer().run(true, true, op);
} catch (InterruptedException e) { // $codepro.audit.disable logExceptions
return false;
} catch (InvocationTargetException e) {
displayErrorDialog(e.getTargetException());
return false;
}
final IStatus status = op.getStatus();
if (!status.isOK()) {
ErrorDialog.openError(getContainer().getShell(),
"Problems during export",
null, // no special message
status);
return false;
}
return true;
}
/**
* The Finish button was pressed. Try to do the required work now and answer
* a boolean indicating success. If false is returned then the wizard will not close.
* @return boolean false if target invalid or export operation fails
*/
@SuppressWarnings("unchecked")
public boolean finish() { // $codepro.audit.disable booleanMethodNamingConvention
final List<IResource> resourcesToExport = getWhiteCheckedResources();
if (!isValidTarget(new File(getDestinationValue()))) {
return false;
}
//Save dirty editors if possible but do not stop if not all are saved
saveDirtyEditors();
// about to invoke the operation so save our state
saveWidgetValues();
return canExportOperation(new ExportResourceOperation(null,
resourcesToExport, getDestinationValue(), this));
}
/**
* Answer the string to display in self as the destination type
*
@return java.lang.String */
protected String getDestinationLabel() {
return "Export to directory";
}
/**
* Answer the contents of self's destination specification widget
*
@return java.lang.String */
protected String getDestinationValue() {
return destinationNameField.getText().trim();
}
/**
* Set the current input focus to self's destination entry field
*/
protected void giveFocusToDestination() {
destinationNameField.setFocus();
}
/**
* Open an appropriate destination browser so that the user can specify a source
* to import from
*/
protected void handleDestinationBrowseButtonPressed() {
final DirectoryDialog dialog = new DirectoryDialog(getContainer().getShell(), SWT.SAVE);
dialog.setMessage(SELECT_DESTINATION_MESSAGE);
dialog.setText(SELECT_DESTINATION_TITLE);
dialog.setFilterPath(getDestinationValue());
final String selectedDirectoryName = dialog.open();
if (null != selectedDirectoryName) {
setErrorMessage(null);
setDestinationValue(selectedDirectoryName);
}
}
/**
* Handle all events and enablements for widgets in this page
* @param e event to handle
* @see org.eclipse.swt.widgets.Listener#handleEvent(Event) */
public void handleEvent(Event e) {
final Widget source = e.widget;
if (destinationBrowseButton.equals(source)) {
handleDestinationBrowseButtonPressed();
}
updatePageCompletion();
}
/**
* Hook method for saving widget values for restoration by the next instance
* of this class.
*/
protected void internalSaveWidgetValues() {
// update directory names history
final IDialogSettings settings = getDialogSettings();
if (null != settings) {
String[] directoryNames = settings
.getArray(STORE_DESTINATION_NAMES_ID);
if (null == directoryNames) {
directoryNames = EMPTY_DIRECTORY_NAMES;
}
directoryNames = addToHistory(directoryNames, getDestinationValue());
settings.put(STORE_DESTINATION_NAMES_ID, directoryNames);
// options
settings.put(STORE_OVERWRITE_EXISTING_FILES_ID,
overwriteExistingFilesCheckbox.getSelection());
settings.put(STORE_CREATE_STRUCTURE_ID,
createDirectoryStructureButton.getSelection());
}
}
/**
* Hook method for restoring widget values to the values that they held
* last time this wizard was used to completion.
*/
protected void restoreWidgetValues() {
final IDialogSettings settings = getDialogSettings();
if (null != settings) {
final String[] directoryNames = settings
.getArray(STORE_DESTINATION_NAMES_ID);
if (null == directoryNames) {
return; // ie.- no settings stored
}
// destination
setDestinationValue(directoryNames[0]);
for (int i = 0; i < directoryNames.length; i++) {
addDestinationItem(directoryNames[i]);
}
// options
overwriteExistingFilesCheckbox.setSelection(settings
.getBoolean(STORE_OVERWRITE_EXISTING_FILES_ID));
boolean createDirectories = settings
.getBoolean(STORE_CREATE_STRUCTURE_ID);
createDirectoryStructureButton.setSelection(createDirectories);
createSelectionOnlyButton.setSelection(!createDirectories);
}
}
/**
* Set the contents of the receivers destination specification widget to
* the passed value
*
* @param value String
*/
protected void setDestinationValue(String value) {
destinationNameField.setText(value);
}
/**
* Answer a boolean indicating whether the receivers destination specification
* widgets currently all contain valid values.
* @return boolean */
protected boolean validateDestinationGroup() {
final String destinationValue = getDestinationValue();
if (0 == destinationValue.length()) {
setMessage(destinationEmptyMessage());
return false;
}
final String conflictingContainer = getConflictingContainerNameFor(destinationValue);
if (null == conflictingContainer) {
// no error message, but warning may exists
final String threatenedContainer = getOverlappingProjectName(destinationValue);
if (null == threatenedContainer) {
setMessage(null);
}
else {
setMessage("Potential conflicting container", WARNING);
}
} else {
setErrorMessage("Conflicting container");
giveFocusToDestination();
return false;
}
return true;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.dialogs.WizardDataTransferPage#validateSourceGroup()
*/
/**
* Method validateSourceGroup.
* @return boolean */
protected boolean validateSourceGroup() {
// there must be some resources selected for Export
boolean isValid = true;
@SuppressWarnings("unchecked")
final List<IResource> resourcesToExport = getWhiteCheckedResources();
if (0 == resourcesToExport.size()){
setErrorMessage("No files selected");
isValid = false;
} else {
setErrorMessage(null);
}
return super.validateSourceGroup() && isValid;
}
/**
* Get the message used to denote an empty destination.
* @return String */
protected String destinationEmptyMessage() {
return "Empty destination";
}
/**
* Returns the name of a container with a location that encompasses targetDirectory.
* Returns null if there is no conflict.
*
* @param targetDirectory the path of the directory to check.
* @return the conflicting container name or <code>null */
protected String getConflictingContainerNameFor(String targetDirectory) {
final IPath rootPath = ResourcesPlugin.getWorkspace().getRoot().getLocation();
final IPath testPath = new Path(targetDirectory);
// cannot export into workspace root
if(testPath.equals(rootPath)) {
return rootPath.lastSegment();
}
//Are they the same?
if(testPath.matchingFirstSegments(rootPath) == rootPath.segmentCount()){
final String firstSegment = testPath.removeFirstSegments(rootPath.segmentCount()).segment(0);
if(!Character.isLetterOrDigit(firstSegment.charAt(0))) {
return firstSegment;
}
}
return null;
}
/**
* Returns the name of a {@link IProject} with a location that includes
* targetDirectory. Returns null if there is no such {@link IProject}.
* @param targetDirectory the path of the directory to check.
* @return the overlapping project name or <code>null */
private String getOverlappingProjectName(String targetDirectory){
final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
// IPath testPath = new Path(targetDirectory);
// IContainer[] containers = root.findContainersForLocation(testPath);
final IContainer[] containers;
try {
containers = root.findContainersForLocationURI(new URI(targetDirectory));
}
catch (URISyntaxException e) {
CertWareLog.logError("Exporting resource", e);
return null;
}
catch(IllegalArgumentException e) {
// not a workspace absolute location
return null;
}
if(containers.length > 0){
return containers[0].getProject().getName();
}
return null;
}
}