/*
* 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.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.List;
import org.deidentifier.arx.DataType;
import org.deidentifier.arx.DataType.DataTypeDescription;
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.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.graphics.Image;
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.Label;
import org.eclipse.swt.widgets.Shell;
/**
* An dialog that allows ordering data items.
*
* @author Fabian Prasser
*/
public class DialogOrderSelection extends TitleAreaDialog implements IDialog {
/** A list control. */
private org.eclipse.swt.widgets.List list;
/** Logo. */
private Image image;
/** Controller. */
private Controller controller;
/** Elements. */
private String[] elements;
/** Type. */
private DataType<?> type;
/** Combo control. */
private Combo combo;
/** Locale. */
private Locale locale;
/**
* Creates a new instance.
*
* @param parentShell
* @param elements
* @param type
* @param locale
* @param controller
*/
public DialogOrderSelection(final Shell parentShell,
final String[] elements,
final DataType<?> type,
final Locale locale,
final Controller controller) {
super(parentShell);
this.controller = controller;
this.image = controller.getResources().getManagedImage("logo_small.png"); //$NON-NLS-1$
this.elements = elements.clone();
this.type = type;
this.locale = locale;
}
@Override
public boolean close() {
return super.close();
}
/**
* Returns the result.
*
* @return
*/
public String[] getResult() {
return elements;
}
/**
* Move an item down.
*/
private void down() {
final int index = list.getSelectionIndex();
if ((index != -1) && (index < (list.getItemCount() - 1))) {
final String temp = elements[index + 1];
elements[index + 1] = elements[index];
elements[index] = temp;
list.setItems(elements);
list.setSelection(index + 1);
}
}
/**
* Returns a description for the given label.
*
* @param label
* @return
*/
private DataTypeDescription<?> getDataType(String label){
for (DataTypeDescription<?> desc : DataType.list()){
if (label.equals(desc.getLabel())){
return desc;
}
}
throw new RuntimeException(Resources.getMessage("DialogOrderSelection.0")+label); //$NON-NLS-1$
}
/**
* Returns the labels of all available data types.
*
* @return
*/
private String[] getDataTypes(){
ArrayList<String> list = new ArrayList<String>();
for (DataTypeDescription<?> desc : DataType.list()){
if (!desc.getLabel().equals("Ordinal")) { //$NON-NLS-1$
list.add(desc.getLabel());
}
}
return list.toArray(new String[list.size()]);
}
/**
* Returns the index of a given data type.
*
* @param type
* @return
*/
private int getIndexOfDataType(DataType<?> type){
int idx = 0;
for (DataTypeDescription<?> desc : DataType.list()){
if (desc.getLabel().equals(type.getDescription().getLabel())) {
return idx;
}
idx++;
}
throw new RuntimeException(Resources.getMessage("DialogOrderSelection.2")+type.getDescription().getLabel()); //$NON-NLS-1$
}
/**
* Checks whether the data type is valid.
*
* @param type
* @param values
* @return
*/
private boolean isValidDataType(DataType<?> type, String[] values) {
for (String value : values) {
if (!type.isValid(value)) { return false; }
}
return true;
}
/**
* Loads the array from a file. If the file contains more or additional
* values (lines) than present in the attribute's domain, the loading is
* aborted and an <code>IllegalStateException</code> is thrown.
*
* @param file
* @param charset
* TODO
* @return
* @throws IllegalStateException
* The file contains more or additional values (lines) than
* present in the attribute's domain
*/
private List<String> loadFile(String file, Charset charset) {
List<String> list = new ArrayList<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));
String line = reader.readLine();
Set<String> _elements = new HashSet<String>();
_elements.addAll(Arrays.asList(elements));
while (line != null) {
list.add(line);
if (list.size() > _elements.size() || !_elements.contains(line)) {
// The file contains more or additional values (lines) than present in the attribute's domain
controller.actionShowInfoDialog(getShell(),
Resources.getMessage("DialogOrderSelection.16"),
Resources.getMessage("DialogOrderSelection.17"));
return null;
}
line = reader.readLine();
}
if (list.size() != _elements.size()) {
// The file contains less values (lines) than present in the attribute's domain
controller.actionShowInfoDialog(getShell(),
Resources.getMessage("DialogOrderSelection.16"),
Resources.getMessage("DialogOrderSelection.17"));
return null;
}
} catch (IOException e) {
controller.actionShowInfoDialog(getShell(),
Resources.getMessage("DialogOrderSelection.3"), //$NON-NLS-1$
Resources.getMessage("DialogOrderSelection.4") + e.getMessage()); //$NON-NLS-1$
return null;
} finally {
if (reader != null) try {
reader.close();
} catch (IOException e) {
controller.actionShowInfoDialog(getShell(),
Resources.getMessage("DialogOrderSelection.5"), //$NON-NLS-1$
Resources.getMessage("DialogOrderSelection.6") + e.getMessage()); //$NON-NLS-1$
return null;
}
}
return list;
}
/**
* Saves the array to file.
*
* @param file
* @param elements
*/
private void saveArray(String file, String[] elements) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(new File(file)));
for (int i=0; i<elements.length; i++) {
writer.write(elements[i]);
if (i<elements.length-1) writer.write("\n"); //$NON-NLS-1$
}
} catch (IOException e) {
controller.actionShowInfoDialog(getShell(), Resources.getMessage("DialogOrderSelection.8"), Resources.getMessage("DialogOrderSelection.9")+e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
} finally {
if (writer != null) try {
writer.close();
} catch (IOException e) {
controller.actionShowInfoDialog(getShell(), Resources.getMessage("DialogOrderSelection.10"), Resources.getMessage("DialogOrderSelection.11")+e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
/**
* Perform sorting.
*
* @param type
*/
private void sort(final DataType<?> type) {
list.removeAll();
Arrays.sort(elements, new Comparator<String>() {
@Override public int compare(final String arg0, final String arg1) {
try {
return type.compare(arg0, arg1);
} catch (final ParseException e) {
throw new RuntimeException(e);
}
}
});
for (final String s : elements) {
list.add(s);
}
}
/**
* Move an item up.
*/
private void up() {
final int index = list.getSelectionIndex();
if ((index != -1) && (index > 0)) {
final String temp = elements[index - 1];
elements[index - 1] = elements[index];
elements[index] = temp;
list.setItems(elements);
list.setSelection(index - 1);
}
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setImages(Resources.getIconSet(newShell.getDisplay()));
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
parent.setLayoutData(SWTUtil.createFillGridData());
// Create IMPORT Button
final Button importButton = createButton(parent,
Integer.MAX_VALUE-1,
Resources.getMessage("DialogOrderSelection.12"), false); //$NON-NLS-1$
importButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
String file = controller.actionShowOpenFileDialog(getShell(), "*.csv"); //$NON-NLS-1$
if (file != null) {
List<String> fileData = loadFile(file, Charset.defaultCharset());
if (fileData != null) {
// Select "Custom"
for (int i = 0; i < combo.getItems().length; i++) {
if (combo.getItem(i).equals(Resources.getMessage("HierarchyWizardPageOrder.8"))) { //$NON-NLS-1$
combo.select(i);
}
}
// Set items
elements = fileData.toArray(new String[fileData.size()]);
list.setItems(elements);
}
}
}
});
// Create EXPORT Button
final Button exportButton = createButton(parent,
Integer.MAX_VALUE-2,
Resources.getMessage("DialogOrderSelection.13"), false); //$NON-NLS-1$
exportButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
String file = controller.actionShowSaveFileDialog(getShell(), "*.csv"); //$NON-NLS-1$
if (file != null) {
saveArray(file, elements);
}
}
});
// Create OK Button
final Button okButton = createButton(parent,
Window.OK,
Resources.getMessage("DialogOrderSelection.14"), true); //$NON-NLS-1$
okButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
setReturnCode(Window.OK);
close();
}
});
// Create CANCEL Button
final Button cancelButton = createButton(parent,
Window.CANCEL,
Resources.getMessage("DialogOrderSelection.15"), false); //$NON-NLS-1$
cancelButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
setReturnCode(Window.CANCEL);
close();
}
});
}
@Override
protected Control createContents(Composite parent) {
Control contents = super.createContents(parent);
setTitle("Specify an order"); //$NON-NLS-1$
setMessage("Please order the list of data items"); //$NON-NLS-1$
if (image!=null) setTitleImage(image); //$NON-NLS-1$
return contents;
}
@Override
protected Control createDialogArea(final Composite parent) {
final GridLayout compositeLayout = new GridLayout();
compositeLayout.numColumns = 1;
parent.setLayout(compositeLayout);
list = new org.eclipse.swt.widgets.List(parent, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
// Limit to 10 entries
final int itemHeight = list.getItemHeight();
final GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
data.heightHint = 10 * itemHeight;
list.setLayoutData(data);
final Composite bottom2 = new Composite(parent, SWT.NONE);
bottom2.setLayoutData(SWTUtil.createFillHorizontallyGridData());
final GridLayout bottomLayout2 = new GridLayout();
bottomLayout2.numColumns = 2;
bottom2.setLayout(bottomLayout2);
final Button up = new Button(bottom2, SWT.NONE);
up.setText(Resources.getMessage("HierarchyWizardPageOrder.3")); //$NON-NLS-1$
up.setImage(controller.getResources().getManagedImage("arrow_up.png")); //$NON-NLS-1$
up.setLayoutData(SWTUtil.createFillHorizontallyGridData());
up.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent arg0) {
up();
}
});
final Button down = new Button(bottom2, SWT.NONE);
down.setText(Resources.getMessage("HierarchyWizardPageOrder.5")); //$NON-NLS-1$
down.setImage(controller.getResources().getManagedImage("arrow_down.png")); //$NON-NLS-1$
down.setLayoutData(SWTUtil.createFillHorizontallyGridData());
down.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent arg0) {
down();
}
});
final Composite bottom1 = new Composite(parent, SWT.NONE);
bottom1.setLayoutData(SWTUtil.createFillHorizontallyGridData());
final GridLayout bottomLayout = new GridLayout();
bottomLayout.numColumns = 2;
bottom1.setLayout(bottomLayout);
final Label text = new Label(bottom1, SWT.NONE);
text.setText(Resources.getMessage("HierarchyWizardPageOrder.7")); //$NON-NLS-1$
combo = new Combo(bottom1, SWT.NONE);
combo.setLayoutData(SWTUtil.createFillHorizontallyGridData());
combo.add(Resources.getMessage("HierarchyWizardPageOrder.8")); //$NON-NLS-1$
for (String type : getDataTypes()){
combo.add(type);
}
combo.select(0);
combo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent arg0) {
if (combo.getSelectionIndex() >=0 ){
DataType<?> type = DialogOrderSelection.this.type;
if (combo.getSelectionIndex() > 0) {
String label = combo.getItem(combo.getSelectionIndex());
DataTypeDescription<?> description = getDataType(label);
// Open format dialog
if (description.hasFormat()) {
final String text1 = Resources.getMessage("AttributeDefinitionView.9"); //$NON-NLS-1$
final String text2 = Resources.getMessage("AttributeDefinitionView.10"); //$NON-NLS-1$
final String format = controller.actionShowFormatInputDialog(getShell(), text1, text2, locale, description, elements);
if (format == null) {
type = DataType.STRING;
combo.select(getIndexOfDataType(DataType.STRING)+1);
} else {
type = description.newInstance(format, locale);
}
} else {
type = description.newInstance();
if (!isValidDataType(type, elements)) {
type = DataType.STRING;
combo.select(getIndexOfDataType(DataType.STRING)+1);
}
}
}
try {
sort(type);
} catch (Exception e){
sort(DataType.STRING);
}
}
}
});
sort(this.type);
return parent;
}
@Override
protected boolean isResizable() {
return false;
}
}