/*
* Copyright (c) 2012 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:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.functions.numeric;
import java.util.List;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
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.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import eu.esdihumboldt.cst.functions.numeric.sequentialid.SequentialIDConstants;
import eu.esdihumboldt.hale.common.align.extension.function.FunctionUtil;
import eu.esdihumboldt.hale.common.align.model.Cell;
import eu.esdihumboldt.hale.common.align.model.Entity;
import eu.esdihumboldt.hale.common.align.model.ParameterValue;
import eu.esdihumboldt.hale.common.align.transformation.function.TransformationVariables;
import eu.esdihumboldt.hale.common.align.transformation.function.impl.DefaultTransformationVariables;
import eu.esdihumboldt.hale.common.core.io.project.ProjectInfoService;
import eu.esdihumboldt.hale.common.core.io.project.ProjectVariables;
import eu.esdihumboldt.hale.common.schema.model.Definition;
import eu.esdihumboldt.hale.common.schema.model.PropertyDefinition;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
import eu.esdihumboldt.hale.common.schema.model.constraint.type.ValidationConstraint;
import eu.esdihumboldt.hale.ui.HaleUI;
import eu.esdihumboldt.hale.ui.HaleWizardPage;
import eu.esdihumboldt.hale.ui.function.generic.pages.AbstractParameterPage;
import eu.esdihumboldt.hale.ui.service.project.ProjectVariablesContentProposalProvider;
import eu.esdihumboldt.hale.ui.util.viewer.EnumContentProvider;
import eu.esdihumboldt.util.validator.Validator;
/**
* Parameter page for the sequential ID function.
*
* @author Simon Templer
*/
public class SequentialIDParameterPage extends AbstractParameterPage implements
SequentialIDConstants {
private ComboViewer sequence;
private Text prefix;
private Text suffix;
private Label example;
private ControlDecoration exampleDecoration;
private ProjectVariablesContentProposalProvider contentProposalProvider = new ProjectVariablesContentProposalProvider(
true);
/**
* Default constructor.
*/
public SequentialIDParameterPage() {
super(FunctionUtil.getPropertyFunction(ID, HaleUI.getServiceProvider()),
"Please configure the identifier generation");
}
/**
* @see AbstractParameterPage#getConfiguration()
*/
@Override
public ListMultimap<String, ParameterValue> getConfiguration() {
ListMultimap<String, ParameterValue> result = ArrayListMultimap.create(3, 1);
if (sequence != null) {
ISelection sel = sequence.getSelection();
if (!sel.isEmpty() && sel instanceof IStructuredSelection) {
result.put(PARAM_SEQUENCE, new ParameterValue(
((Sequence) ((IStructuredSelection) sel).getFirstElement()).name()));
}
}
if (prefix != null) {
result.put(PARAM_PREFIX, new ParameterValue(prefix.getText()));
}
if (suffix != null) {
result.put(PARAM_SUFFIX, new ParameterValue(suffix.getText()));
}
return result;
}
/**
* @see HaleWizardPage#createContent(Composite)
*/
@Override
protected void createContent(Composite page) {
page.setLayout(GridLayoutFactory.swtDefaults().numColumns(2).spacing(10, 8).create());
Label label;
GridDataFactory labelLayout = GridDataFactory.swtDefaults().align(SWT.END, SWT.CENTER);
GridDataFactory controlLayout = GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER)
.grab(true, false);
// select sequence type
if (getParametersToHandle().containsKey(PARAM_SEQUENCE)) {
label = new Label(page, SWT.NONE);
label.setText("Sequence");
labelLayout.applyTo(label);
sequence = new ComboViewer(page);
sequence.setContentProvider(EnumContentProvider.getInstance());
sequence.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof Sequence) {
switch ((Sequence) element) {
case overall:
return "Over all sequential IDs";
case type:
return "Per target instance type";
}
}
return super.getText(element);
}
});
sequence.setInput(Sequence.class);
controlLayout.applyTo(sequence.getControl());
Sequence initialValue = Sequence.valueOf(getOptionalInitialValue(PARAM_SEQUENCE,
new ParameterValue(Sequence.type.name())).as(String.class));
sequence.setSelection(new StructuredSelection(initialValue));
sequence.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateStatus();
}
});
}
// specify prefix
if (getParametersToHandle().containsKey(PARAM_PREFIX)) {
label = new Label(page, SWT.NONE);
label.setText("Prefix");
labelLayout.applyTo(label);
prefix = new Text(page, SWT.SINGLE | SWT.BORDER);
controlLayout.applyTo(prefix);
prefix.setText(getOptionalInitialValue(PARAM_PREFIX, new ParameterValue("")).as(
String.class));
prefix.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
updateStatus();
}
});
ContentProposalAdapter adapter = new ContentProposalAdapter(prefix,
new TextContentAdapter(), contentProposalProvider,
ProjectVariablesContentProposalProvider.CTRL_SPACE, new char[] { '{' });
adapter.setAutoActivationDelay(0);
final ControlDecoration infoDeco = new ControlDecoration(prefix, SWT.TOP | SWT.LEFT);
infoDeco.setDescriptionText("Type Ctrl+Space for project variable content assistance");
infoDeco.setImage(FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION).getImage());
infoDeco.setMarginWidth(2);
}
// specify suffix
if (getParametersToHandle().containsKey(PARAM_SUFFIX)) {
label = new Label(page, SWT.NONE);
label.setText("Suffix");
labelLayout.applyTo(label);
suffix = new Text(page, SWT.SINGLE | SWT.BORDER);
controlLayout.applyTo(suffix);
suffix.setText(getOptionalInitialValue(PARAM_SUFFIX, new ParameterValue("")).as(
String.class));
suffix.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
updateStatus();
}
});
ContentProposalAdapter adapter = new ContentProposalAdapter(suffix,
new TextContentAdapter(), contentProposalProvider,
ProjectVariablesContentProposalProvider.CTRL_SPACE, new char[] { '{' });
adapter.setAutoActivationDelay(0);
final ControlDecoration infoDeco = new ControlDecoration(suffix, SWT.TOP | SWT.LEFT);
infoDeco.setDescriptionText("Type Ctrl+Space for project variable content assistance");
infoDeco.setImage(FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION).getImage());
infoDeco.setShowOnlyOnFocus(true);
}
// show example
if (sequence != null && prefix != null && suffix != null) {
label = new Label(page, SWT.NONE);
label.setText("Example");
labelLayout.applyTo(label);
example = new Label(page, SWT.NONE);
example.setFont(JFaceResources.getTextFont());
controlLayout.applyTo(example);
// error decoration
exampleDecoration = new ControlDecoration(example, SWT.LEFT | SWT.TOP, page);
FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
exampleDecoration.setImage(fieldDecoration.getImage());
exampleDecoration.hide();
}
updateStatus();
}
/**
* Update the example and the page status
*/
protected void updateStatus() {
boolean complete = true;
if (example != null) {
String exampleStr = generateExample();
example.setText(exampleStr);
boolean valid = validateValue(exampleStr);
if (!valid) {
complete = false;
setMessage("The generated identifier is not valid for the target property", ERROR);
}
else {
setMessage(null);
}
}
if (sequence != null && sequence.getSelection().isEmpty()) {
complete = false;
}
setPageComplete(complete);
}
/**
* @see HaleWizardPage#onShowPage(boolean)
*/
@Override
protected void onShowPage(boolean firstShow) {
super.onShowPage(firstShow);
// the target property might have changed
updateStatus();
}
/**
* Validates if the given value is valid for the target property.
*
* @param value the value to validate
* @return if the value is valid
*/
protected boolean validateValue(String value) {
Cell cell = getWizard().getUnfinishedCell();
List<? extends Entity> targets = cell.getTarget().get(null);
if (!targets.isEmpty()) {
Entity entity = targets.get(0);
Definition<?> def = entity.getDefinition().getDefinition();
if (def instanceof PropertyDefinition) {
TypeDefinition propertyType = ((PropertyDefinition) def).getPropertyType();
Validator validator = propertyType.getConstraint(ValidationConstraint.class)
.getValidator();
// TODO conversion to binding needed?
String error = validator.validate(value);
// update the example decoration
if (error == null) {
exampleDecoration.hide();
}
else {
exampleDecoration.setDescriptionText(error);
exampleDecoration.show();
}
return error == null;
}
}
// no validation possible
return true;
}
/**
* Generate an identifier example from the current configuration.
*
* @return the identifier example
*/
protected String generateExample() {
String prefix = (this.prefix == null) ? ("") : (this.prefix.getText());
String suffix = (this.suffix == null) ? ("") : (this.suffix.getText());
// replace variables in prefix and suffix
TransformationVariables variables = new DefaultTransformationVariables(new ProjectVariables(
HaleUI.getServiceProvider().getService(ProjectInfoService.class)));
prefix = variables.replaceVariables(prefix);
suffix = variables.replaceVariables(suffix);
return prefix + START_VALUE + suffix;
}
}