/******************************************************************************* | |
* Copyright (c) 2014 Hussein Mhanna | |
* | |
* 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: | |
* Hussein Mhanna - initial API and implementation | |
******************************************************************************/ | |
package org.eclipse.rmf.reqif10.csv.importer.ui.wizards.pages; | |
import java.io.File; | |
import org.eclipse.core.resources.IFile; | |
import org.eclipse.core.resources.ResourcesPlugin; | |
import org.eclipse.jface.viewers.ArrayContentProvider; | |
import org.eclipse.jface.viewers.ComboViewer; | |
import org.eclipse.jface.viewers.ISelectionChangedListener; | |
import org.eclipse.jface.viewers.IStructuredSelection; | |
import org.eclipse.jface.viewers.LabelProvider; | |
import org.eclipse.jface.viewers.SelectionChangedEvent; | |
import org.eclipse.jface.viewers.StructuredSelection; | |
import org.eclipse.jface.viewers.TreeViewer; | |
import org.eclipse.jface.viewers.Viewer; | |
import org.eclipse.jface.viewers.ViewerFilter; | |
import org.eclipse.jface.wizard.WizardPage; | |
import org.eclipse.swt.SWT; | |
import org.eclipse.swt.events.ModifyEvent; | |
import org.eclipse.swt.events.ModifyListener; | |
import org.eclipse.swt.events.SelectionAdapter; | |
import org.eclipse.swt.events.SelectionEvent; | |
import org.eclipse.swt.layout.GridData; | |
import org.eclipse.swt.layout.GridLayout; | |
import org.eclipse.swt.widgets.Button; | |
import org.eclipse.swt.widgets.Composite; | |
import org.eclipse.swt.widgets.FileDialog; | |
import org.eclipse.swt.widgets.Group; | |
import org.eclipse.swt.widgets.Label; | |
import org.eclipse.swt.widgets.Text; | |
import org.eclipse.ui.model.BaseWorkbenchContentProvider; | |
import org.eclipse.ui.model.WorkbenchLabelProvider; | |
/** | |
* | |
* @author Hussein MHANNA | |
* | |
*/ | |
public class CSVImportWizardPage extends WizardPage { | |
/** | |
* The reqif file extension | |
*/ | |
private static final String REQIF_EXTENSION = "reqif"; | |
/** | |
* The reqif file extension | |
*/ | |
private static final String CSV_EXTENSION = "csv"; | |
/** | |
* | |
*/ | |
private static final String[] CSV_SEPARATOR_ARRAY = new String[] { ",", | |
";", ":", ".", "\t", "|", "^" }; | |
/** | |
* The selected path to the file | |
*/ | |
private String selectedFilePath = ""; | |
/** | |
* The csv separator | |
*/ | |
private String separator = CSV_SEPARATOR_ARRAY[0]; | |
/** | |
* Indicate if the csv contains a header | |
*/ | |
private boolean containsHeader; | |
/** | |
* The selected path to the file | |
*/ | |
private IFile selectedDestinationFile; | |
/** | |
* The constructor | |
*/ | |
public CSVImportWizardPage() { | |
super("Import requirements from CSV"); | |
setTitle("Import requirements from CSV"); | |
setDescription("Requirements CSV File Import Wizard"); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
@Override | |
public void createControl(final Composite parent) { | |
final Composite mainComposite = new Composite(parent, SWT.NONE); | |
mainComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, | |
true, true)); | |
final GridLayout gridLayout = new GridLayout(); | |
mainComposite.setLayout(gridLayout); | |
createFileSelectionGroup(mainComposite); | |
createConfigurationGroup(mainComposite); | |
createReqIFFileSelectionComposite(mainComposite); | |
validatePage(); | |
setControl(mainComposite); | |
} | |
/** | |
* Create the file selection group. | |
* | |
* @param parent | |
* : The parent composite | |
*/ | |
protected Group createFileSelectionGroup(final Composite parent) { | |
final Group group = createGroup(parent, "File Selection"); | |
createLabel(group, "File :"); | |
final Text text = createText(group); | |
text.addModifyListener(new ModifyListener() { | |
@Override | |
public void modifyText(ModifyEvent e) { | |
selectedFilePath = text.getText(); | |
validatePage(); | |
} | |
}); | |
final Button button = createButton(group, "Browse"); | |
button.addSelectionListener(new SelectionAdapter() { | |
@Override | |
public void widgetSelected(final SelectionEvent e) { | |
final String filePath = browseForFile(); | |
if ((filePath != null) && !filePath.isEmpty()) { | |
text.setText(filePath); | |
} | |
} | |
}); | |
return group; | |
} | |
/** | |
* Create the configuration group. | |
* | |
* @param parent | |
* : The parent composite | |
*/ | |
protected Group createConfigurationGroup(final Composite parent) { | |
final Group group = createGroup(parent, "Configuration"); | |
createLabel(group, "Separator character"); | |
ComboViewer comboViewer = new ComboViewer(group); | |
comboViewer.setContentProvider(new ArrayContentProvider()); | |
comboViewer.setLabelProvider(new LabelProvider()); | |
comboViewer.setInput(CSV_SEPARATOR_ARRAY); | |
comboViewer.setSelection(new StructuredSelection(separator)); | |
comboViewer | |
.addSelectionChangedListener(new ISelectionChangedListener() { | |
@Override | |
public void selectionChanged(SelectionChangedEvent event) { | |
separator = ((IStructuredSelection) event | |
.getSelection()).getFirstElement().toString(); | |
} | |
}); | |
comboViewer.getCombo().setLayoutData( | |
new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1)); | |
final Button headerButton = new Button(group, SWT.CHECK); | |
headerButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, | |
3, 1)); | |
headerButton.setText("The csv file contains a header"); | |
headerButton.addSelectionListener(new SelectionAdapter() { | |
@Override | |
public void widgetSelected(SelectionEvent e) { | |
super.widgetSelected(e); | |
containsHeader = headerButton.getSelection(); | |
} | |
}); | |
return group; | |
} | |
/** | |
* Create the file destination selection group. | |
* | |
* @param parent | |
* : The parent composite | |
*/ | |
protected Group createFileDestinationSelectionGroup(final Composite parent) { | |
final Group group = createGroup(parent, "ReqIF File destination"); | |
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); | |
createReqIFFileSelectionComposite(group); | |
return group; | |
} | |
/** | |
* Create a {@link Group} | |
* | |
* @param parent | |
* : The parent composite | |
* @param groupText | |
* : The group text | |
* @return The created {@link Group} | |
*/ | |
private Group createGroup(final Composite parent, String groupText) { | |
Group group = new Group(parent, SWT.NONE); | |
group.setText(groupText); | |
group.setLayout(new GridLayout(3, false)); | |
group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1)); | |
return group; | |
} | |
/** | |
* Create a {@link Label} | |
* | |
* @param parent | |
* : The parent composite | |
* @param labelText | |
* : The label text | |
* @return The created {@link Label} | |
*/ | |
protected Label createLabel(final Composite parent, String labelText) { | |
final Label label = new Label(parent, SWT.NONE); | |
label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, | |
1, 1)); | |
label.setText(labelText); | |
return label; | |
} | |
/** | |
* Create a {@link Text} | |
* | |
* @param parent | |
* : The parent composite | |
* @return The created {@link Text} | |
*/ | |
protected Text createText(final Composite parent) { | |
Text text = new Text(parent, SWT.BORDER); | |
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); | |
return text; | |
} | |
/** | |
* Create a button with the text "Browse..." | |
* | |
* @param parent | |
* : The parent composite | |
* @param buttonText | |
* : The button text | |
* @return The created button | |
*/ | |
protected Button createButton(final Composite parent, String buttonText) { | |
final Button button = new Button(parent, SWT.NONE); | |
button.setText(buttonText); | |
return button; | |
} | |
/** | |
* Create the file selection composite | |
* | |
* @param parent | |
* : The parent composite | |
*/ | |
protected void createReqIFFileSelectionComposite(Composite parent) { | |
Group group = createGroup(parent, "Destination ReqIF File"); | |
group.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, | |
true)); | |
TreeViewer treeViewer = new TreeViewer(group); | |
treeViewer.getTree().setLayoutData( | |
new GridData(GridData.FILL, GridData.FILL, true, true)); | |
treeViewer.setContentProvider(new BaseWorkbenchContentProvider()); | |
treeViewer.setLabelProvider(new WorkbenchLabelProvider()); | |
ViewerFilter reqifFilter = new ViewerFilter() { | |
@Override | |
public boolean select(Viewer viewer, Object parentElement, | |
Object element) { | |
if (element instanceof IFile) { | |
return isReqIFFile((IFile) element); | |
} | |
return true; | |
} | |
}; | |
treeViewer.setFilters(new ViewerFilter[] { reqifFilter }); | |
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { | |
@Override | |
public void selectionChanged(SelectionChangedEvent event) { | |
IFile file = null; | |
IStructuredSelection selection = (IStructuredSelection) event | |
.getSelection(); | |
if (false == selection.isEmpty()) { | |
Object object = selection.getFirstElement(); | |
if (object instanceof IFile && isReqIFFile((IFile) object)) { | |
file = (IFile) object; | |
} | |
} | |
selectedDestinationFile = file; | |
validatePage(); | |
} | |
}); | |
treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); | |
} | |
/** | |
* Return whether a file is an reqif file | |
* | |
* @param file | |
* : The file | |
* @return <code>true</code> if the file extsntion is | |
* {@link #REQIF_EXTENSION} and <code>false</code> otherwise | |
*/ | |
protected boolean isReqIFFile(IFile file) { | |
return file.getFileExtension().equals(REQIF_EXTENSION); | |
} | |
/** | |
* Browse for a file | |
* | |
* @return The selected path if any and an empty | |
*/ | |
protected String browseForFile() { | |
final FileDialog dialog = createFileDialog(); | |
final String path = dialog.open(); | |
return path == null ? "" : path; | |
} | |
/** | |
* Create and return {@link FileDialog} | |
* | |
* @return The created {@link FileDialog} | |
*/ | |
protected FileDialog createFileDialog() { | |
final FileDialog dialog = new FileDialog(getShell(), SWT.OPEN); | |
dialog.setFilterExtensions(new String[] { "*." + CSV_EXTENSION }); | |
return dialog; | |
} | |
/** | |
* Update the status of the page, if it is complete or not. | |
*/ | |
protected boolean validatePage() { | |
boolean valid = true; | |
if (selectedFilePath.isEmpty()) { | |
setFieldEmptyErrorMessage(); | |
valid = false; | |
} else if (false == checkFileExtension(selectedFilePath)) { | |
setExtensionErrorMessage(); | |
valid = false; | |
} else if (false == isFileExist(selectedFilePath)) { | |
setNoFileErrorMessage(selectedFilePath); | |
valid = false; | |
} else if (selectedDestinationFile == null) { | |
setSelectedReqIFDestinationFileEmptyErrorMessage(); | |
valid = false; | |
} | |
if (valid) { | |
setPageComplete(true); | |
setMessage(null); | |
setErrorMessage(null); | |
} | |
return valid; | |
} | |
/** | |
* Check if the extension file is compatible. | |
* | |
* @param path | |
* : The path | |
* @return <code>true</code> if the file extension is compatible and | |
* <code>false</code> otherwise | |
*/ | |
protected boolean checkFileExtension(final String path) { | |
return path.endsWith("."+CSV_EXTENSION); | |
} | |
/** | |
* Check if the given file path is valid. | |
* | |
* @param filePath | |
* : The path | |
* @return <code>true</code> if the path is valid (exist on the disk) and | |
* <code>false</code> otherwise | |
*/ | |
protected boolean isFileExist(final String filePath) { | |
return new File(filePath).exists(); | |
} | |
/** | |
* Set the error message indicating that the text field is empty | |
*/ | |
protected void setFieldEmptyErrorMessage() { | |
setMessage(null); | |
setErrorMessage(" Please select a csv file to import"); | |
setPageComplete(false); | |
} | |
/** | |
* Set the error message indicating that the file must end with .csv | |
*/ | |
protected void setExtensionErrorMessage() { | |
setMessage(null); | |
setErrorMessage("The file name must end with .csv"); | |
setPageComplete(false); | |
} | |
/** | |
* Set the error message indicating that the file doesn't exist | |
* | |
* @param fileName | |
* : The file name | |
*/ | |
protected void setNoFileErrorMessage(final String fileName) { | |
setMessage(null); | |
setErrorMessage("The file " + fileName + "doesn't exists"); | |
setPageComplete(false); | |
} | |
/** | |
* Set the error message indicating that not selected reqif destination file | |
* selected | |
*/ | |
protected void setSelectedReqIFDestinationFileEmptyErrorMessage() { | |
setMessage(null); | |
setErrorMessage(" Please select the destination ReqIF file (*.reqif)"); | |
setPageComplete(false); | |
} | |
/** | |
* Get the selected file path. | |
* | |
* @return the selected file path | |
*/ | |
public String getSelectedFilePath() { | |
return selectedFilePath; | |
} | |
/** | |
* Return the separator | |
* | |
* @return The separator | |
*/ | |
public char getSeparator() { | |
return separator.charAt(0); | |
} | |
/** | |
* Return the selected destination file | |
* | |
* @return The selected destination file | |
*/ | |
public IFile getSelectedDestinationFile() { | |
return selectedDestinationFile; | |
} | |
/** | |
* Return whether the csv file contains a header | |
* | |
* @return <code>true</code> if the csv file contains a header and | |
* <code>false</code> otherwise | |
*/ | |
public boolean isContainsHeader() { | |
return containsHeader; | |
} | |
} |