/*
* ARX: Powerful Data Anonymization
* Copyright 2012 - 2017 Fabian Prasser, Florian Kohlmayer and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deidentifier.arx.gui.view.impl.menu;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.deidentifier.arx.gui.Controller;
import org.deidentifier.arx.gui.resources.Resources;
import org.deidentifier.arx.gui.view.SWTUtil;
import org.deidentifier.arx.gui.view.def.IDialog;
import org.deidentifier.arx.io.CSVDataInput;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
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.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
/**
*
*/
public class DialogSeparator extends TitleAreaDialog implements IDialog {
/** Constant */
private static final int LINES = 5;
/** View */
private Table table;
/** Model */
private int selection;
/** Model */
private final char[] separators = { ';', ',', '|', '\t' }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
/** Model */
private final String[] labels = { ";", ",", "|", "Tab" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
/** Model */
private final String file;
/** Model */
private final boolean data;
/**
*
*
* @param parent
* @param controller
* @param file
* @param data
*/
public DialogSeparator(final Shell parent,
final Controller controller,
final String file,
boolean data) {
super(parent);
this.file = file;
this.data = data;
}
@Override
public void create() {
super.create();
setTitle(Resources.getMessage("SeparatorDialog.4")); //$NON-NLS-1$
setMessage(Resources.getMessage("SeparatorDialog.5"), IMessageProvider.INFORMATION); //$NON-NLS-1$
super.getShell().setSize(500, 350);
super.getShell().layout();
SWTUtil.center(super.getShell(), super.getParentShell());
}
/**
*
*
* @return
*/
public char getSeparator() {
return separators[selection];
}
/**
* Detects the most frequent separator in the first few lines.
*
* @param file
* @param charset TODO
* @throws IOException
*/
private void detect(final String file, Charset charset) throws IOException {
// Open file
final BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));
// Count chars
int count = 0;
String line = r.readLine();
final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
while ((count < LINES) && (line != null)) {
final char[] a = line.toCharArray();
for (final char c : a) {
for (int i = 0; i < separators.length; i++) {
if (c == separators[i]) {
if (!map.containsKey(i)) {
map.put(i, 0);
}
map.put(i, map.get(i) + 1);
}
}
}
line = r.readLine();
count++;
}
// Close
r.close();
// Choose max
if (map.isEmpty()) { return; }
int max = Integer.MIN_VALUE;
for (final int key : map.keySet()) {
if (map.get(key) > max) {
max = map.get(key);
selection = key;
}
}
}
/**
* Reds the first few files with chosen separator.
*
* @param file
* @throws IOException
*/
private void read(final String file, final Charset charset) throws IOException {
// Read the first few lines
final CSVDataInput in = new CSVDataInput(file, charset, separators[selection]);
final Iterator<String[]> it = in.iterator();
final List<String[]> data = new ArrayList<String[]>();
int count = 0;
while (it.hasNext() && (count < LINES)) {
data.add(it.next());
count++;
}
in.close();
// In case of hierarchy, add header
if (!this.data && data.size() > 0) {
// Duplicate last entry
data.add(data.get(data.size() - 1));
// Shift all entries
for (int i = data.size() - 2; i >= 0; i--) {
data.set(i + 1, data.get(i));
}
// Add header
int length = data.get(0).length;
String[] header = new String[length];
for (int i = 0; i < length; i++) {
header[i] = Resources.getMessage("SeparatorDialog.6") + (i + 1); //$NON-NLS-1$
}
data.set(0, header);
}
// Add to table
table.setRedraw(false);
table.removeAll();
for (final TableColumn c : table.getColumns()) {
c.dispose();
}
if (data.size() == 0) { return; }
for (final String s : data.get(0)) {
final TableColumn c = new TableColumn(table, SWT.NONE);
c.setText(s);
c.pack();
}
for (int i = 1; i < data.size(); i++) {
final TableItem item = new TableItem(table, SWT.NONE);
for (int j = 0; j < data.get(i).length; j++) {
item.setText(j, data.get(i)[j]);
}
}
table.setRedraw(true);
table.redraw();
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setImages(Resources.getIconSet(newShell.getDisplay()));
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
// Create OK Button
parent.setLayoutData(SWTUtil.createFillGridData());
final Button ok = createButton(parent,
Window.OK,
Resources.getMessage("SeparatorDialog.7"), true); //$NON-NLS-1$
ok.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
setReturnCode(Window.OK);
close();
}
});
// Create cancel Button
parent.setLayoutData(SWTUtil.createFillGridData());
final Button cancel = createButton(parent,
Window.CANCEL,
Resources.getMessage("SeparatorDialog.8"), false); //$NON-NLS-1$
cancel.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
setReturnCode(Window.CANCEL);
close();
}
});
}
@Override
protected Control createDialogArea(final Composite parent) {
parent.setLayout(new GridLayout());
final GridLayout l = new GridLayout();
l.numColumns = 2;
parent.setLayout(l);
// Build components
table = SWTUtil.createTable(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
GridData d = SWTUtil.createFillGridData();
d.horizontalSpan = 2;
d.grabExcessHorizontalSpace = true;
d.grabExcessVerticalSpace = true;
table.setLayoutData(d);
table.setHeaderVisible(true);
table.setLinesVisible(true);
try {
detect(file, Charset.defaultCharset());
read(file, Charset.defaultCharset());
} catch (final Exception e) {
if (e instanceof RuntimeException){
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
final Combo combo = new Combo(parent, SWT.NONE);
d = SWTUtil.createFillHorizontallyGridData();
d.horizontalSpan = 2;
combo.setLayoutData(d);
for (final String s : labels) {
combo.add(s);
}
combo.select(selection);
combo.pack();
combo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent arg0) {
try {
if (combo.getSelectionIndex() == -1) { return; }
selection = combo.getSelectionIndex();
read(file, Charset.defaultCharset());
} catch (final Exception e) {
if (e instanceof RuntimeException){
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
}
});
return parent;
}
@Override
protected ShellListener getShellListener() {
return new ShellAdapter() {
@Override
public void shellClosed(final ShellEvent event) {
event.doit = false;
}
};
}
@Override
protected boolean isResizable() {
return false;
}
}