View Javadoc

1   /*
2    * This file is a part of CAST project.
3    * (c) Copyright 2007, AGH University of Science & Technology
4    * https://caribou.iisg.agh.edu.pl/trac/cast
5    *
6    * Licensed under the Eclipse Public License, Version 1.0 (the "License").
7    * You may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * http://www.eclipse.org/legal/epl-v10.html
10   */
11  /*
12   * File: DelimiterSelectionPageComposite.java
13   * Created: 2009-03-09
14   * Author: bmilos
15   * $Id$
16   */
17  
18  package pl.edu.agh.cast.importer.wizard.page;
19  
20  import java.util.HashSet;
21  import java.util.LinkedList;
22  import java.util.List;
23  import java.util.Set;
24  
25  import org.eclipse.jface.viewers.TableViewer;
26  import org.eclipse.swt.SWT;
27  import org.eclipse.swt.events.FocusAdapter;
28  import org.eclipse.swt.events.FocusEvent;
29  import org.eclipse.swt.events.ModifyEvent;
30  import org.eclipse.swt.events.ModifyListener;
31  import org.eclipse.swt.events.SelectionAdapter;
32  import org.eclipse.swt.events.SelectionEvent;
33  import org.eclipse.swt.events.VerifyEvent;
34  import org.eclipse.swt.events.VerifyListener;
35  import org.eclipse.swt.layout.GridData;
36  import org.eclipse.swt.layout.GridLayout;
37  import org.eclipse.swt.widgets.Button;
38  import org.eclipse.swt.widgets.Combo;
39  import org.eclipse.swt.widgets.Composite;
40  import org.eclipse.swt.widgets.Group;
41  import org.eclipse.swt.widgets.Label;
42  import org.eclipse.swt.widgets.Text;
43  
44  import pl.edu.agh.cast.importer.base.data.RawTabularData;
45  import pl.edu.agh.cast.importer.base.tokenizer.ITokenizerOption;
46  import pl.edu.agh.cast.importer.base.tokenizer.TokenizerOption;
47  import pl.edu.agh.cast.importer.base.tokenizer.csv.CsvTokenizer;
48  import pl.edu.agh.cast.importer.wizard.util.Messages;
49  import pl.edu.agh.cast.importer.wizard.utils.AbstractWizardPageHelper;
50  import pl.edu.agh.cast.importer.wizard.utils.TableViewerHelper;
51  
52  /**
53   * The main composite of the {@link DelimiterSelectionPage}.
54   *
55   * @author AGH CAST Team
56   */
57  public class DelimiterSelectionPageComposite extends Composite {
58  
59  	private static final Character COMMA = ',';
60  
61  	private static final Character SEMICOMMA = ';';
62  
63  	private static final Character SPACE = ' ';
64  
65  	private static final Character TAB = '\t';
66  
67  	private DelimiterSelectionPage mediator;
68  
69  	private Composite fileTypeSelectionComposite;
70  
71  	private Label mergeSplitInstructionLbl;
72  
73  	private TableViewer previewTableViewer;
74  
75  	private Group filePreviewGroup;
76  
77  	private Text otherDelimiterTxt;
78  
79  	private Combo textQualifierCombo;
80  
81  	private Button textQualifierChbox;
82  
83  	private Button otherChbox;
84  
85  	private Button tabChbox;
86  
87  	private Button spaceChbox;
88  
89  	private Group delimitersGroup;
90  
91  	private Button semicommaChbox;
92  
93  	private Button commaChbox;
94  
95  	private Composite optionsComposite;
96  
97  	private Text commentCharTxt;
98  
99  	private Button commentCharChbox;
100 
101 	private Set<Character> selectedDelimiters;
102 
103 	private RawTabularData previewData;
104 
105 	private String currentFilePath = ""; //$NON-NLS-1$
106 
107 	/**
108 	 * The default constructor.
109 	 *
110 	 * @param parent
111 	 *            the parent composite
112 	 * @param style
113 	 *            the style of widget to construct
114 	 * @param mediator
115 	 *            the mediating wizard page
116 	 */
117 	public DelimiterSelectionPageComposite(Composite parent, int style, DelimiterSelectionPage mediator) {
118 		super(parent, style);
119 		this.mediator = mediator;
120 		this.selectedDelimiters = new HashSet<Character>();
121 		initGUI();
122 	}
123 
124 	private void initGUI() {
125 		GridLayout thisLayout = new GridLayout(2, false);
126 		thisLayout.verticalSpacing = 10;
127 		thisLayout.horizontalSpacing = 30;
128 		this.setLayout(thisLayout);
129 		this.setSize(800, 600);
130 
131 		fileTypeSelectionComposite = new Composite(this, SWT.NONE);
132 		GridLayout fileTypeSelectionCompositeLayout = new GridLayout(2, false);
133 		GridData dataFileParamsCompositeLData = new GridData();
134 		dataFileParamsCompositeLData.verticalAlignment = GridData.BEGINNING;
135 		dataFileParamsCompositeLData.minimumWidth = 750;
136 		dataFileParamsCompositeLData.minimumHeight = 100;
137 		fileTypeSelectionComposite.setLayoutData(dataFileParamsCompositeLData);
138 		fileTypeSelectionComposite.setLayout(fileTypeSelectionCompositeLayout);
139 
140 		optionsComposite = new Composite(this, SWT.NONE);
141 		GridLayout optionsCompositeLayout = new GridLayout(2, true);
142 		optionsCompositeLayout.horizontalSpacing = 20;
143 		optionsCompositeLayout.verticalSpacing = 10;
144 		GridData optionsCompositeLData = new GridData(SWT.CENTER, SWT.CENTER, false, false);
145 		optionsCompositeLData.horizontalAlignment = GridData.CENTER;
146 		optionsComposite.setLayout(optionsCompositeLayout);
147 		optionsComposite.setLayoutData(optionsCompositeLData);
148 
149 		textQualifierChbox = new Button(optionsComposite, SWT.CHECK);
150 		GridData textQualifierLblLData = new GridData(SWT.FILL, SWT.CENTER, true, false);
151 		textQualifierLblLData.minimumWidth = 80;
152 		textQualifierChbox.setLayoutData(textQualifierLblLData);
153 		textQualifierChbox.setText(Messages.DelimiterSelectionPageComposite_TextQualifier);
154 		textQualifierChbox.setToolTipText(Messages.DelimiterSelectionPageComposite_TextQualifierTooltip);
155 		textQualifierChbox.addSelectionListener(new SelectionAdapter() {
156 			@Override
157 			public void widgetSelected(SelectionEvent event) {
158 				handleTextQualifierChboxSelection();
159 			}
160 		});
161 
162 		textQualifierCombo = new Combo(optionsComposite, SWT.READ_ONLY);
163 		GridData textQualifierComboLData = new GridData(SWT.FILL, SWT.CENTER, true, false);
164 		textQualifierComboLData.minimumWidth = 50;
165 		textQualifierComboLData.minimumHeight = 20;
166 		textQualifierCombo.setLayoutData(textQualifierComboLData);
167 		textQualifierCombo.setItems(AbstractWizardPageHelper.TEXT_QUALIFIERS);
168 		textQualifierCombo.setEnabled(false);
169 		textQualifierCombo.select(0);
170 		textQualifierCombo.addSelectionListener(new SelectionAdapter() {
171 			@Override
172 			public void widgetSelected(SelectionEvent event) {
173 				handleTextQualifierSelection();
174 			}
175 		});
176 
177 		commentCharChbox = new Button(optionsComposite, SWT.CHECK | SWT.LEFT);
178 		commentCharChbox.setText(Messages.DelimiterSelectionPageComposite_CommentChar);
179 		GridData commentCharChboxLData = new GridData(SWT.FILL, SWT.CENTER, true, false);
180 		commentCharChbox.setLayoutData(commentCharChboxLData);
181 		commentCharChbox.setToolTipText(Messages.DelimiterSelectionPageComposite_CommentCharTooltip);
182 		commentCharChbox.addSelectionListener(new SelectionAdapter() {
183 			@Override
184 			public void widgetSelected(SelectionEvent event) {
185 				handleCommentCharChboxSelection();
186 			}
187 		});
188 
189 		commentCharTxt = new Text(optionsComposite, SWT.BORDER);
190 		GridData commentCharTxtLData = new GridData(SWT.FILL, SWT.CENTER, true, false);
191 		commentCharTxtLData.heightHint = 15;
192 		commentCharTxt.setLayoutData(commentCharTxtLData);
193 		commentCharTxt.setEnabled(false);
194 		commentCharTxt.addVerifyListener(new VerifyListener() {
195 			public void verifyText(VerifyEvent event) {
196 				AbstractWizardPageHelper.handleCommentCharVerification(event);
197 			}
198 		});
199 		commentCharTxt.addFocusListener(new FocusAdapter() {
200 			public void focusLost(FocusEvent e) {
201 				refreshFilePreview();
202 			}
203 		});
204 
205 		delimitersGroup = new Group(fileTypeSelectionComposite, SWT.NONE);
206 		GridLayout delimitersGroupLayout = new GridLayout(2, false);
207 		GridData delimitersGroupLData = new GridData();
208 		delimitersGroup.setLayoutData(delimitersGroupLData);
209 		delimitersGroup.setLayout(delimitersGroupLayout);
210 		delimitersGroup.setText(Messages.DelimiterSelectionPageComposite_Delimiters);
211 
212 		commaChbox = new Button(delimitersGroup, SWT.CHECK | SWT.LEFT);
213 		GridData commaChboxLData = new GridData();
214 		commaChboxLData.horizontalSpan = 2;
215 		commaChbox.setLayoutData(commaChboxLData);
216 		commaChbox.setText(Messages.DelimiterSelectionPageComposite_Comma);
217 		commaChbox.addSelectionListener(new SelectionAdapter() {
218 			@Override
219 			public void widgetSelected(SelectionEvent event) {
220 				refreshSelectedDelimitersList();
221 			}
222 		});
223 
224 		semicommaChbox = new Button(delimitersGroup, SWT.CHECK | SWT.LEFT);
225 		GridData semicommaChboxLData = new GridData();
226 		semicommaChboxLData.horizontalSpan = 2;
227 		semicommaChbox.setLayoutData(semicommaChboxLData);
228 		semicommaChbox.setText(Messages.DelimiterSelectionPageComposite_Semicolon);
229 		semicommaChbox.addSelectionListener(new SelectionAdapter() {
230 			@Override
231 			public void widgetSelected(SelectionEvent event) {
232 				refreshSelectedDelimitersList();
233 			}
234 		});
235 
236 		spaceChbox = new Button(delimitersGroup, SWT.CHECK | SWT.LEFT);
237 		GridData spaceChboxLData = new GridData();
238 		spaceChboxLData.horizontalSpan = 2;
239 		spaceChbox.setLayoutData(spaceChboxLData);
240 		spaceChbox.setText(Messages.DelimiterSelectionPageComposite_Space);
241 		spaceChbox.addSelectionListener(new SelectionAdapter() {
242 			@Override
243 			public void widgetSelected(SelectionEvent event) {
244 				refreshSelectedDelimitersList();
245 			}
246 		});
247 
248 		tabChbox = new Button(delimitersGroup, SWT.CHECK | SWT.LEFT);
249 		GridData tabChboxLData = new GridData();
250 		tabChboxLData.horizontalSpan = 2;
251 		tabChbox.setLayoutData(tabChboxLData);
252 		tabChbox.setText(Messages.DelimiterSelectionPageComposite_Tab);
253 		tabChbox.addSelectionListener(new SelectionAdapter() {
254 			@Override
255 			public void widgetSelected(SelectionEvent event) {
256 				refreshSelectedDelimitersList();
257 			}
258 		});
259 
260 		otherChbox = new Button(delimitersGroup, SWT.CHECK | SWT.LEFT);
261 		GridData otherChboxLData = new GridData(SWT.BEGINNING, SWT.CENTER, true, false);
262 		otherChboxLData.minimumWidth = 94;
263 		otherChbox.setLayoutData(otherChboxLData);
264 		otherChbox.setText(Messages.DelimiterSelectionPageComposite_Other);
265 		otherChbox.addSelectionListener(new SelectionAdapter() {
266 			@Override
267 			public void widgetSelected(SelectionEvent event) {
268 				refreshSelectedDelimitersList();
269 			}
270 		});
271 
272 		otherDelimiterTxt = new Text(delimitersGroup, SWT.BORDER);
273 		otherDelimiterTxt.setEnabled(false);
274 		otherDelimiterTxt.addVerifyListener(new VerifyListener() {
275 			public void verifyText(VerifyEvent event) {
276 				handleOtherDelimiterVerification(event);
277 			}
278 		});
279 		otherDelimiterTxt.addModifyListener(new ModifyListener() {
280 			public void modifyText(ModifyEvent event) {
281 				refreshSelectedDelimitersList();
282 			}
283 		});
284 
285 		mergeSplitInstructionLbl = new Label(this, SWT.WRAP);
286 		GridData mergeSplitInstructionLblLData = new GridData(SWT.FILL, SWT.CENTER, true, false);
287 		mergeSplitInstructionLblLData.minimumWidth = 700;
288 		mergeSplitInstructionLblLData.minimumHeight = 30;
289 		mergeSplitInstructionLblLData.horizontalSpan = 2;
290 		mergeSplitInstructionLblLData.widthHint = 780;
291 		mergeSplitInstructionLblLData.heightHint = 30;
292 		mergeSplitInstructionLbl.setBounds(10, 10, 780, 30);
293 		mergeSplitInstructionLbl.setLayoutData(mergeSplitInstructionLblLData);
294 		mergeSplitInstructionLbl.setText(Messages.DelimiterSelectionPageComposite_MergeSplitInstructionLabel);
295 
296 		filePreviewGroup = new Group(this, SWT.NONE);
297 		GridLayout filePreviewGroupLayout = new GridLayout();
298 		filePreviewGroup.setLayout(filePreviewGroupLayout);
299 		GridData filePreviewGroupLData = new GridData(SWT.FILL, SWT.FILL, true, true);
300 		filePreviewGroupLData.horizontalSpan = 3;
301 		filePreviewGroupLData.minimumWidth = 550;
302 		filePreviewGroupLData.minimumHeight = 150;
303 		filePreviewGroup.setLayoutData(filePreviewGroupLData);
304 		filePreviewGroup.setText(Messages.DelimiterSelectionPageComposite_FilePreview);
305 
306 		previewTableViewer = new TableViewer(filePreviewGroup, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL
307 		        | SWT.H_SCROLL);
308 		GridData previewTableViewerLData = new GridData(SWT.FILL, SWT.FILL, true, true);
309 		previewTableViewerLData.minimumWidth = 500;
310 		previewTableViewerLData.minimumHeight = 100;
311 		previewTableViewer.getControl().setLayoutData(previewTableViewerLData);
312 	}
313 
314 	/*
315 	 * -----------------------------------------------------------------------------------------------------------
316 	 * --------------------------ACTION METHODS------------------------------------------------------------
317 	 * -----------------------------------------------------------------------------------------------------------
318 	 */
319 
320 	private void handleTextQualifierChboxSelection() {
321 		textQualifierCombo.setEnabled(textQualifierChbox.getSelection());
322 		refreshFilePreview();
323 	}
324 
325 	private void handleCommentCharChboxSelection() {
326 		commentCharTxt.setEnabled(commentCharChbox.getSelection());
327 		refreshFilePreview();
328 	}
329 
330 	private void refreshSelectedDelimitersList() {
331 		selectedDelimiters.clear();
332 		if (commaChbox.getSelection()) {
333 			selectedDelimiters.add(COMMA);
334 		}
335 		if (semicommaChbox.getSelection()) {
336 			selectedDelimiters.add(SEMICOMMA);
337 		}
338 		if (spaceChbox.getSelection()) {
339 			selectedDelimiters.add(SPACE);
340 		}
341 		if (tabChbox.getSelection()) {
342 			selectedDelimiters.add(TAB);
343 		}
344 		if (otherChbox.getSelection() && !otherDelimiterTxt.getText().isEmpty()) {
345 			selectedDelimiters.add(otherDelimiterTxt.getText().charAt(0));
346 		}
347 		otherDelimiterTxt.setEnabled(otherChbox.getSelection());
348 		refreshFilePreview();
349 	}
350 
351 	private void handleOtherDelimiterVerification(VerifyEvent event) {
352 		// Assume the character is not allowed
353 		event.doit = false;
354 
355 		// Get the character typed
356 		char inputChar = event.character;
357 		String text = ((Text)event.widget).getText();
358 
359 		// Allow any text shorter than a single character
360 		if (text.length() <= 0) {
361 			event.doit = true;
362 		}
363 
364 		// Allow backspace
365 		if (inputChar == '\b') {
366 			event.doit = true;
367 		}
368 	}
369 
370 	private void handleTextQualifierSelection() {
371 		refreshFilePreview();
372 	}
373 
374 	/*----------------------------------------------------------------------------------------------------------*/
375 
376 	/*
377 	 * -----------------------------------------------------------------------------------------------------------
378 	 * --------------------------HELPER METHODS------------------------------------------------------------
379 	 * -----------------------------------------------------------------------------------------------------------
380 	 */
381 
382 	/**
383 	 * Retrieves the selected tokenizer options.
384 	 *
385 	 * @return selected options
386 	 */
387 	public List<ITokenizerOption> getSelectedTokenizerOptions() {
388 		final List<ITokenizerOption> options = new LinkedList<ITokenizerOption>();
389 		if (!selectedDelimiters.isEmpty()) {
390 			options.add(new TokenizerOption(CsvTokenizer.RECORD_SEPARATOR_OPTION_NAME, createDelimetersRegexString()));
391 		}
392 		if (textQualifierChbox.getSelection()) {
393 			options.add(new TokenizerOption(CsvTokenizer.QUALIFIER_OPTION_NAME, textQualifierCombo
394 			        .getItem(textQualifierCombo.getSelectionIndex())));
395 		}
396 		if (commentCharChbox.getSelection() && !commentCharTxt.getText().isEmpty()) {
397 			options.add(new TokenizerOption(CsvTokenizer.COMMENT_CHAR_OPTION_NAME, commentCharTxt.getText()));
398 		}
399 		return options;
400 	}
401 
402 	private String createDelimetersRegexString() {
403 		final StringBuilder regex = new StringBuilder();
404 		regex.append("["); //$NON-NLS-1$
405 		for (Character delimiter : selectedDelimiters) {
406 			regex.append(delimiter);
407 		}
408 		regex.append("]"); //$NON-NLS-1$
409 		return regex.toString();
410 	}
411 
412 	private void clearTokenizerOptions() {
413 		commentCharChbox.setSelection(false);
414 		textQualifierChbox.setSelection(false);
415 		handleCommentCharChboxSelection();
416 		handleTextQualifierChboxSelection();
417 
418 		spaceChbox.setSelection(false);
419 		semicommaChbox.setSelection(false);
420 		commaChbox.setSelection(false);
421 		otherChbox.setSelection(false);
422 		tabChbox.setSelection(false);
423 		selectedDelimiters.clear();
424 	}
425 
426 	/**
427 	 * Refreshes the file preview.
428 	 */
429 	public void refreshFilePreview() {
430 		final List<ITokenizerOption> pageOptions = getSelectedTokenizerOptions();
431 		if (pageOptions.equals(mediator.getImportProcess().getTokenizer().getTokenizerOptions())) {
432 			return;
433 		}
434 
435 		previewData = mediator.loadPreview(pageOptions, AbstractWizardPageHelper.PREVIEW_ROWS_LIMIT_PARTIAL);
436 
437 		if (previewData != null) {
438 			previewTableViewer.getTable().setEnabled(true);
439 			TableViewerHelper.initTable(previewTableViewer, previewData);
440 			previewTableViewer.getTable().setLinesVisible(true);
441 			previewTableViewer.getTable().setHeaderVisible(true);
442 			TableViewerHelper.adjustColumnWidth(previewTableViewer);
443 		}
444 	}
445 
446 	/**
447 	 * Refreshes the file preview group label by adding to it the selected data file path name.
448 	 *
449 	 * @param selectedFilePath
450 	 *            the selected file path
451 	 */
452 	public void refreshFilePreviewGroupLabel(String selectedFilePath) {
453 		if (!currentFilePath.equals(mediator.getImportProcess().getFilePath())) {
454 			final StringBuilder sb = new StringBuilder();
455 			sb.append(Messages.InitImportPageComposite_FilePreview);
456 			sb.append(": "); //$NON-NLS-1$
457 			sb.append(selectedFilePath);
458 			filePreviewGroup.setText(sb.toString());
459 			clearTokenizerOptions();
460 
461 			this.currentFilePath = selectedFilePath;
462 		}
463 	}
464 
465 	/*----------------------------------------------------------------------------------------------------------*/
466 
467 }