/*
* Copyright (c) 2013 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.io.csv.ui;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
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.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.supplier.LocatableInputSupplier;
import eu.esdihumboldt.hale.common.schema.io.SchemaReader;
import eu.esdihumboldt.hale.io.csv.PropertyTypeExtension;
import eu.esdihumboldt.hale.io.csv.PropertyTypeFactory;
import eu.esdihumboldt.hale.io.csv.reader.CommonSchemaConstants;
import eu.esdihumboldt.hale.io.csv.reader.internal.AbstractTableSchemaReader;
import eu.esdihumboldt.hale.ui.HaleWizardPage;
import eu.esdihumboldt.hale.ui.io.IOWizardPage;
import eu.esdihumboldt.hale.ui.io.config.AbstractConfigurationPage;
import eu.esdihumboldt.hale.ui.io.schema.SchemaReaderConfigurationPage;
import eu.esdihumboldt.hale.ui.util.components.DynamicScrolledComposite;
/**
* Default schema type configuration page <br>
* Override onPage() method to set firstLine (header) and nextLine (content) and
* call super method
*
* @author Kevin Mais
* @author Patrick Lieb
*/
public class DefaultSchemaTypePage extends SchemaReaderConfigurationPage {
private String defaultString = "";
/**
* Field editor for editing the schema name as string
*/
private StringFieldEditor sfe;
private Group group;
private String[] lastSecondRow = null;
private final List<TypeNameField> fields = new ArrayList<TypeNameField>();
private final List<ComboViewer> comboFields = new ArrayList<ComboViewer>();
private ScrolledComposite sc;
private final List<Boolean> validSel = new ArrayList<Boolean>();
private Boolean valid = true;
private Boolean isValid = true;
private String[] header;
private String[] secondRow;
/**
* default constructor
*
* @param pageName the page name
*/
public DefaultSchemaTypePage(String pageName) {
super(pageName);
setTitle("Typename Settings");
setDescription("Enter a valid Name for your Type");
}
/**
* @see IOWizardPage#updateConfiguration
*/
@Override
public boolean updateConfiguration(SchemaReader provider) {
provider.setParameter(CommonSchemaConstants.PARAM_TYPENAME, Value.of(sfe.getStringValue()));
StringBuffer propNamesBuffer = new StringBuffer();
StringBuffer comboViewerBuffer = new StringBuffer();
StringBuffer oldNamesBuffer = new StringBuffer();
for (TypeNameField prop : fields) {
propNamesBuffer.append(prop.getStringValue());
propNamesBuffer.append(",");
}
propNamesBuffer.deleteCharAt(propNamesBuffer.lastIndexOf(","));
String propNames = propNamesBuffer.toString();
for (String string : lastSecondRow) {
oldNamesBuffer.append(string);
oldNamesBuffer.append(",");
}
oldNamesBuffer.deleteCharAt(oldNamesBuffer.lastIndexOf(","));
String oldNames = oldNamesBuffer.toString();
if (oldNames.equals(propNames)) {
provider.setParameter(CommonSchemaConstants.PARAM_SKIP_FIRST_LINE, Value.of("True"));
}
else {
provider.setParameter(CommonSchemaConstants.PARAM_SKIP_FIRST_LINE, Value.of("False"));
}
provider.setParameter(AbstractTableSchemaReader.PARAM_PROPERTY, Value.of(propNames));
for (ComboViewer combo : comboFields) {
comboViewerBuffer.append(((PropertyTypeFactory) ((IStructuredSelection) combo
.getSelection()).getFirstElement()).getIdentifier());
comboViewerBuffer.append(",");
}
comboViewerBuffer.deleteCharAt(comboViewerBuffer.lastIndexOf(","));
String combViewNames = comboViewerBuffer.toString();
provider.setParameter(AbstractTableSchemaReader.PARAM_PROPERTYTYPE, Value.of(combViewNames));
return true;
}
/**
* @see HaleWizardPage#onShowPage(boolean)
*/
@Override
protected void onShowPage(boolean firstShow) {
super.onShowPage(firstShow);
LocatableInputSupplier<? extends InputStream> source = getWizard().getProvider()
.getSource();
int indexStart = 0;
int indexEnd = source.getLocation().getPath().length() - 1;
// set the content of this page, type name and property name with data
// type
update();
// get schema name based on file name
if (source.getLocation().getPath() != null) {
indexStart = source.getLocation().getPath().lastIndexOf("/") + 1;
if (source.getLocation().getPath().lastIndexOf(".") >= 0) {
indexEnd = source.getLocation().getPath().lastIndexOf(".");
}
// set type name
defaultString = source.getLocation().getPath().substring(indexStart, indexEnd);
sfe.setStringValue(defaultString);
// setPageComplete(sfe.isValid());
}
// Content has changed so clear everything (if this is not first visit)
// if (!firstShow && lastSecondRow != null && !Arrays.equals(header, lastSecondRow)) {
// clearPage();
// }
}
/**
* Update all fields (should be called if page is initialized or the
* selection of input (file or table) has been changed
*/
protected void update() {
int length = 0;
// the header is not valid so clear all content
if (header == null || header.length == 0) {
// clear properties
clearPage();
return;
}
if (secondRow == null || secondRow.length == 0) {
secondRow = header;
}
if (header.length != 0) {
length = header.length;
}
// dispose all property names if the read configuration has been changed
if (lastSecondRow != null && !Arrays.equals(header, lastSecondRow)) {
for (TypeNameField properties : fields) {
properties.dispose();
properties.getTextControl(group).dispose();
properties.getLabelControl(group).dispose();
}
for (ComboViewer combViewer : comboFields) {
combViewer.getCombo().dispose();
}
fields.clear();
comboFields.clear();
}
if (!Arrays.equals(header, lastSecondRow)) {
for (int i = 0; i < length; i++) {
final TypeNameField propField;
final ComboViewer cv;
validSel.add(true);
propField = new TypeNameField("properties", Integer.toString(i + 1), group);
fields.add(propField);
propField.setEmptyStringAllowed(false);
propField.setErrorMessage("Please enter a valid Property Name");
propField.setPropertyChangeListener(new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
HashSet<String> hs = new HashSet<String>();
if (event.getProperty().equals(StringFieldEditor.VALUE)) {
for (TypeNameField field : fields) {
if (!hs.add(field.getStringValue())) {
valid = false;
break;
}
else {
valid = true;
}
}
}
if (event.getProperty().equals(StringFieldEditor.IS_VALID)) {
isValid = (Boolean) event.getNewValue();
}
setPageComplete(isValid());
}
});
propField.setStringValue(header[i].replace(" ", ""));
cv = new ComboViewer(group);
comboFields.add(cv);
cv.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
int i = comboFields.indexOf(event.getSource());
PropertyTypeFactory actualSelection = ((PropertyTypeFactory) ((IStructuredSelection) cv
.getSelection()).getFirstElement());
try {
actualSelection.createExtensionObject().convertFromField(secondRow[i]);
validSel.set(i, true);
} catch (Exception e) {
validSel.set(i, false);
}
if (validSel.contains(false)) {
int j = validSel.indexOf(false) + 1;
setMessage("Your selection in field # " + j + " is not valid!", WARNING);
}
else {
setMessage(null);
}
}
});
cv.setContentProvider(ArrayContentProvider.getInstance());
cv.setLabelProvider(new LabelProvider() {
/**
* @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
*/
@Override
public String getText(Object element) {
if (element instanceof PropertyTypeFactory) {
return ((PropertyTypeFactory) element).getDisplayName();
}
return super.getText(element);
}
});
Collection<PropertyTypeFactory> elements = PropertyTypeExtension.getInstance()
.getFactories();
cv.setInput(elements);
PropertyTypeFactory defaultSelection = PropertyTypeExtension.getInstance()
.getFactory("java.lang.String");
if (defaultSelection != null) {
cv.setSelection(new StructuredSelection(defaultSelection));
}
else if (!elements.isEmpty()) {
cv.setSelection(new StructuredSelection(elements.iterator().next()));
}
}
}
group.setLayout(new GridLayout(3, false));
lastSecondRow = header;
group.layout();
sc.layout();
// setPageComplete(sfe.isValid() && isValid && valid);
}
/**
* Clear the page. Can be called when the content has changed. Set everthing
* on an initial state
*/
private void clearPage() {
// clear properties
for (TypeNameField properties : fields) {
properties.dispose();
properties.getTextControl(group).dispose();
properties.getLabelControl(group).dispose();
}
for (ComboViewer combViewer : comboFields) {
combViewer.getCombo().dispose();
}
validSel.clear();
fields.clear();
comboFields.clear();
sfe.setStringValue("");
group.layout();
sc.layout();
lastSecondRow = null;
}
/**
* @see HaleWizardPage#createContent(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void createContent(Composite parent) {
Composite holder = new Composite(parent, SWT.NONE);
holder.setLayout(GridLayoutFactory.fillDefaults().create());
sc = new DynamicScrolledComposite(holder, SWT.V_SCROLL);
sc.setExpandHorizontal(true);
sc.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, 200)
.create());
Composite page = new Composite(sc, SWT.NONE);
page.setLayout(new GridLayout(2, false));
sfe = new TypeNameField("typename", "Typename", page);
sfe.setEmptyStringAllowed(false);
// sfe.setErrorMessage("Please enter a valid Type Name");
sfe.setPropertyChangeListener(new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(StringFieldEditor.IS_VALID)) {
setPageComplete(isValid());
}
}
});
sfe.setStringValue(defaultString);
// sfe.setPage(this);
group = new Group(page, SWT.NONE);
group.setText("Properties");
group.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).create());
group.setLayout(GridLayoutFactory.swtDefaults().numColumns(3).equalWidth(false)
.margins(5, 5).create());
sc.setContent(page);
sc.layout();
// setPageComplete(sfe.isValid());
}
/**
* @param header the firstLine to set
*/
public void setHeader(String[] header) {
this.header = header;
}
/**
* @param secondRow the nextLine to set
*/
public void setSecondRow(String[] secondRow) {
this.secondRow = secondRow;
}
/**
* @return true, if the state of properties and type names are valid
*/
public boolean isValid() {
if (sfe.isValid() && isValid && valid && header != null && header.length != 0) {
setErrorMessage(null);
return true;
}
else {
showMessage();
return false;
}
}
/**
* Set Message based on not valid condition
*/
private void showMessage() {
if (header == null || header.length == 0)
setErrorMessage("The file contains no data");
else if (!sfe.isValid())
setErrorMessage("Please enter a valid Type Name");
else if (!isValid)
setErrorMessage("Please enter a valid Property Name");
else if (!valid)
setErrorMessage("Doublicated property name is not allowed");
// else if();
}
/**
* @param value the string to set
*/
public void setStringFieldEditorValue(String value) {
this.sfe.setStringValue(value);
}
/**
* @see AbstractConfigurationPage#enable()
*/
@Override
public void enable() {
// not required
}
/**
* @see AbstractConfigurationPage#disable()
*/
@Override
public void disable() {
// not required
}
}