Java tutorial
/** * Copyright (C) 2015 Bonitasoft S.A. * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.studio.contract.ui.wizard; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Sets.newHashSet; import static org.bonitasoft.studio.common.jface.databinding.UpdateStrategyFactory.neverUpdateValueStrategy; import static org.bonitasoft.studio.common.jface.databinding.UpdateStrategyFactory.updateValueStrategy; import static org.bonitasoft.studio.common.jface.databinding.validator.ValidatorFactory.uniqueValidator; import java.util.Collections; import java.util.List; import java.util.Objects; import org.bonitasoft.engine.bdm.model.BusinessObject; import org.bonitasoft.engine.bdm.model.field.Field; import org.bonitasoft.studio.businessobject.core.repository.BusinessObjectModelRepositoryStore; import org.bonitasoft.studio.common.NamingUtils; import org.bonitasoft.studio.contract.core.mapping.FieldToContractInputMapping; import org.bonitasoft.studio.contract.core.mapping.FieldToContractInputMappingFactory; import org.bonitasoft.studio.contract.i18n.Messages; import org.bonitasoft.studio.contract.ui.wizard.labelProvider.FieldNameColumnLabelProvider; import org.bonitasoft.studio.contract.ui.wizard.labelProvider.FieldTypeColumnLabelProvider; import org.bonitasoft.studio.contract.ui.wizard.labelProvider.InputTypeColumnLabelProvider; import org.bonitasoft.studio.model.process.BusinessObjectData; import org.bonitasoft.studio.model.process.Contract; import org.bonitasoft.studio.model.process.ContractInput; import org.bonitasoft.studio.model.process.Element; import org.bonitasoft.studio.model.process.Pool; import org.bonitasoft.studio.model.process.ProcessPackage; import org.bonitasoft.studio.model.process.Task; import org.eclipse.core.databinding.beans.PojoObservables; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.conversion.IConverter; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.core.databinding.observable.set.IObservableSet; import org.eclipse.core.databinding.observable.set.WritableSet; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.SelectObservableValue; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.databinding.validation.MultiValidator; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.databinding.EMFDataBindingContext; import org.eclipse.emf.databinding.EMFObservables; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.viewers.IViewerObservableSet; import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.databinding.wizard.WizardPageSupport; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import com.google.common.base.Function; /** * @author aurelie */ public class CreateContractInputFromBusinessObjectWizardPage extends WizardPage { private static final int DEFAULT_BUTTON_WIDTH_HINT = 85; private final WritableValue selectedDataObservable; private CheckboxTreeViewer treeViewer; private final FieldToContractInputMappingFactory fieldToContractInputMappingFactory; private List<FieldToContractInputMapping> mappings; private String rootName; private final Contract contract; private final BusinessObjectModelRepositoryStore businessObjectStore; private final GenerationOptions generationOptions; private SelectObservableValue actionObservable; private final WritableValue rootNameObservable; private final WritableList fieldToContractInputMappingsObservable; protected CreateContractInputFromBusinessObjectWizardPage(final Contract contract, final GenerationOptions generationOptions, final WritableValue selectedDataObservable, final WritableValue rootNameObservable, final FieldToContractInputMappingFactory fieldToContractInputMappingFactory, final WritableList fieldToContractInputMappingsObservable, final BusinessObjectModelRepositoryStore businessObjectStore) { super(CreateContractInputFromBusinessObjectWizardPage.class.getName()); setDescription(Messages.selectFieldToGenerateDescription); this.selectedDataObservable = selectedDataObservable; this.fieldToContractInputMappingFactory = fieldToContractInputMappingFactory; this.contract = contract; this.generationOptions = generationOptions; this.businessObjectStore = businessObjectStore; this.rootNameObservable = rootNameObservable; this.fieldToContractInputMappingsObservable = fieldToContractInputMappingsObservable; } public void setTitle() { if (selectedDataObservable.getValue() != null) { setTitle(Messages.bind(Messages.selectFieldToGenerateTitle, ((Element) selectedDataObservable.getValue()).getName())); EMFObservables .observeDetailValue(Realm.getDefault(), selectedDataObservable, ProcessPackage.Literals.ELEMENT__NAME) .addValueChangeListener(new IValueChangeListener() { @Override public void handleValueChange(final ValueChangeEvent event) { setTitle(Messages.bind(Messages.selectFieldToGenerateTitle, event.diff.getNewValue())); } }); } }; /* * (non-Javadoc) * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl(final Composite parent) { final EMFDataBindingContext dbc = new EMFDataBindingContext(); WizardPageSupport.create(this, dbc); final Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(10, 10).create()); composite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); createRootNameControl(dbc, composite); createProcessDataMappingTreeViewer(composite, dbc); createReminderText(dbc, composite); setControl(composite); } private void createReminderText(final EMFDataBindingContext dbc, final Composite composite) { final CLabel reminder = new CLabel(composite, SWT.NONE); final Display d = Display.getCurrent(); final Image img = d.getSystemImage(SWT.ICON_WARNING); reminder.setImage(img); reminder.setLayoutData(GridDataFactory.fillDefaults().hint(600, SWT.DEFAULT).create()); final Button autoGeneratedOperationButton = new Button(composite, SWT.RADIO); final Button manuallyDefinedOperationButton = new Button(composite, SWT.RADIO); actionObservable = new SelectObservableValue(Boolean.class); actionObservable.addOption(Boolean.TRUE, SWTObservables.observeSelection(autoGeneratedOperationButton)); actionObservable.addOption(Boolean.FALSE, SWTObservables.observeSelection(manuallyDefinedOperationButton)); if (contract.eContainer() instanceof Task) { reminder.setText(Messages.reminderForStepMessage); autoGeneratedOperationButton.setText(Messages.autoGeneratedOperationStepButton); manuallyDefinedOperationButton.setText(Messages.manuallyDefinedOperationStepButton); } else { reminder.setText(Messages.reminderForProcessMessage); autoGeneratedOperationButton.setText(Messages.autoGeneratedOperationProcessButton); manuallyDefinedOperationButton.setText(Messages.manuallyDefinedOperationProcessButton); } dbc.bindValue(actionObservable, PojoObservables.observeValue(generationOptions, "autogeneratedScript")); } public void disableAutoGeneration() { actionObservable.setValue(false); } private void createRootNameControl(final EMFDataBindingContext dbc, final Composite composite) { final Composite rootNameComposite = new Composite(composite, SWT.NONE); rootNameComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).margins(10, 10).create()); rootNameComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); final Label label = new Label(rootNameComposite, SWT.NONE); label.setLayoutData(GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).create()); label.setText(Messages.rootContractInputName); final Text prefixText = new Text(rootNameComposite, SWT.BORDER); prefixText.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); final Label typeLabel = new Label(rootNameComposite, SWT.NONE); typeLabel.setText(Messages.inputOfType); final IObservableValue prefixObservable = PojoObservables.observeValue(this, "rootName"); dbc.bindValue(prefixObservable, EMFObservables.observeDetailValue(Realm.getDefault(), selectedDataObservable, ProcessPackage.Literals.ELEMENT__NAME), neverUpdateValueStrategy().create(), updateValueStrategy().withConverter(dataNameToRootContractInputName()).create()); dbc.bindValue( SWTObservables.observeText(prefixText, SWT.Modify), prefixObservable, updateValueStrategy() .withValidator(uniqueValidator().onProperty("name").in(contract.getInputs())).create(), null); dbc.bindValue(rootNameObservable, prefixObservable); } private IConverter dataNameToRootContractInputName() { return new Converter(String.class, String.class) { @Override public Object convert(final Object fromObject) { final String className = (String) EMFObservables.observeDetailValue(Realm.getDefault(), selectedDataObservable, ProcessPackage.Literals.JAVA_OBJECT_DATA__CLASS_NAME).getValue(); if (className != null) { final String name = fromObject + "Input"; return NamingUtils.generateNewName( newHashSet(transform(contract.getInputs(), toContactInputName())), name, 0); } return ""; } }; } private Function<ContractInput, String> toContactInputName() { return new Function<ContractInput, String>() { @Override public String apply(final ContractInput input) { return input.getName(); } }; } private void createProcessDataMappingTreeViewer(final Composite composite, final EMFDataBindingContext dbc) { final Composite viewerComposite = new Composite(composite, SWT.NONE); viewerComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); viewerComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).margins(15, 15).create()); treeViewer = new CheckboxTreeViewer(viewerComposite, SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.MULTI); treeViewer.getTree() .setLayoutData(GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, 200).create()); treeViewer.getTree().setHeaderVisible(true); treeViewer.addFilter(hidePersistenceIdMapping()); final FieldToContractInputMappingViewerCheckStateManager manager = new FieldToContractInputMappingViewerCheckStateManager(); treeViewer.addCheckStateListener(manager); treeViewer.setCheckStateProvider(manager); final ObservableListTreeContentProvider provider = new ObservableListTreeContentProvider( new FieldToContractInputMappingObservableFactory(), new FieldToContractInputMappingTreeStructureAdvisor()); treeViewer.setContentProvider(provider); final TreeViewerColumn nameTreeViewerColumn = new TreeViewerColumn(treeViewer, SWT.FILL); nameTreeViewerColumn.getColumn().setText(Messages.attributeName); nameTreeViewerColumn.getColumn().setWidth(250); nameTreeViewerColumn.setLabelProvider(new FieldNameColumnLabelProvider()); final TreeViewerColumn typeTreeViewerColumn = new TreeViewerColumn(treeViewer, SWT.FILL); typeTreeViewerColumn.getColumn().setText(Messages.attributetype); typeTreeViewerColumn.getColumn().setWidth(150); typeTreeViewerColumn.setLabelProvider(new FieldTypeColumnLabelProvider()); final TreeViewerColumn inputTypeTreeViewerColumn = new TreeViewerColumn(treeViewer, SWT.FILL); inputTypeTreeViewerColumn.getColumn().setText(Messages.inputType); inputTypeTreeViewerColumn.getColumn().setWidth(150); inputTypeTreeViewerColumn.setLabelProvider(new InputTypeColumnLabelProvider()); dbc.bindValue(ViewersObservables.observeInput(treeViewer), selectedDataObservable, null, updateValueStrategy().withConverter(selectedDataToFieldMappings()).create()); final IViewerObservableSet checkedElements = ViewersObservables.observeCheckedElements(treeViewer, FieldToContractInputMapping.class); final WritableValue checkedObservableValue = new WritableValue(); checkedObservableValue.setValue(checkedElements); final WritableValue mappingsObservableValue = new WritableValue(); mappingsObservableValue.setValue(fieldToContractInputMappingsObservable); final MultiValidator multiValidator = createEmptySelectionMultivalidator(checkedElements); dbc.addValidationStatusProvider(multiValidator); dbc.bindValue(checkedObservableValue, mappingsObservableValue, updateValueStrategy() .withConverter(createMappingsToCheckedElementsConverter(mappingsObservableValue)).create(), updateValueStrategy().withConverter(createCheckedElementsToMappingsConverter()).create()); createButtonComposite(viewerComposite, manager, checkedElements); } protected Converter createMappingsToCheckedElementsConverter(final WritableValue mappingsObservableValue) { return new Converter(IObservableSet.class, WritableList.class) { @Override public Object convert(final Object fromObject) { final IObservableSet set = (IObservableSet) fromObject; for (final FieldToContractInputMapping mapping : mappings) { mapping.setGenerated(set.contains(mapping)); } return mappingsObservableValue; } }; } protected Converter createCheckedElementsToMappingsConverter() { return new Converter(WritableList.class, IObservableSet.class) { @Override public Object convert(final Object fromObject) { final IObservableSet set = new WritableSet(); for (final FieldToContractInputMapping mapping : mappings) { if (mapping.isGenerated()) { set.add(mapping); } } return set; } }; } protected MultiValidator createEmptySelectionMultivalidator(final IViewerObservableSet checkedElements) { return new MultiValidator() { @Override protected IStatus validate() { if (checkedElements.isEmpty()) { return ValidationStatus.error(Messages.atLeastOneAttributeShouldBeSelectedError); } return ValidationStatus.ok(); } }; } protected void createButtonComposite(final Composite viewerComposite, final FieldToContractInputMappingViewerCheckStateManager manager, final IObservableSet checkElements) { final Composite buttonsComposite = new Composite(viewerComposite, SWT.NONE); buttonsComposite.setLayoutData(GridDataFactory.fillDefaults().grab(false, true).create()); buttonsComposite .setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).spacing(0, 3).create()); final Button selectAll = new Button(buttonsComposite, SWT.FLAT); selectAll.setLayoutData(GridDataFactory.fillDefaults().grab(true, false) .hint(DEFAULT_BUTTON_WIDTH_HINT, SWT.DEFAULT).create()); selectAll.setText(Messages.selectAll); selectAll.addSelectionListener(createSelectAllListener(checkElements)); final Button deselectAll = new Button(buttonsComposite, SWT.FLAT); deselectAll.setText(Messages.deselectAll); deselectAll.setLayoutData(GridDataFactory.fillDefaults().grab(true, false) .hint(DEFAULT_BUTTON_WIDTH_HINT, SWT.DEFAULT).create()); deselectAll.addSelectionListener(createDeselectAllListener(checkElements)); } protected SelectionAdapter createDeselectAllListener(final IObservableSet checkElements) { return new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { checkElements.clear(); generateAllMappings(mappings, false); } }; } protected SelectionAdapter createSelectAllListener(final IObservableSet checkElements) { return new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { checkElements.clear(); checkAllMappings(checkElements, mappings); generateAllMappings(mappings, true); } }; } private ViewerFilter hidePersistenceIdMapping() { return new ViewerFilter() { @Override public boolean select(final Viewer viewer, final Object parentElement, final Object element) { return !Objects.equals(Field.PERSISTENCE_ID, ((FieldToContractInputMapping) element).getField().getName()); } }; } private IConverter selectedDataToFieldMappings() { return new Converter(BusinessObjectData.class, List.class) { @Override public Object convert(final Object selectedData) { if (selectedData == null) { return Collections.emptyList(); } mappings = fieldToContractInputMappingFactory .createMappingForBusinessObjectType(toBusinessObject((BusinessObjectData) selectedData)); fieldToContractInputMappingsObservable.clear(); fieldToContractInputMappingsObservable.addAll(mappings); return mappings; } }; } /* * (non-Javadoc) * @see org.eclipse.jface.wizard.WizardPage#canFlipToNextPage() */ @Override public boolean canFlipToNextPage() { if (contract.eContainer() instanceof Pool) { return generationOptions.isAutogeneratedScript() && super.canFlipToNextPage(); } else { return super.canFlipToNextPage(); } } private BusinessObject toBusinessObject(final BusinessObjectData selectedData) { return businessObjectStore.getBusinessObjectByQualifiedName(selectedData.getClassName()); } public List<FieldToContractInputMapping> getMappings() { return mappings; } public void setMappings(final List<FieldToContractInputMapping> mappings) { this.mappings = mappings; } public String getRootName() { return rootName; } public void setRootName(final String rootName) { this.rootName = rootName; } public void generateAllMappings(final List<FieldToContractInputMapping> mappingList, final boolean state) { for (final FieldToContractInputMapping mapping : mappingList) { if (!Field.PERSISTENCE_ID.equals(mapping.getField().getName())) { mapping.setGenerated(state); generateAllMappings(mapping.getChildren(), state); } } } public void checkAllMappings(final IObservableSet checkedElements, final List<FieldToContractInputMapping> mappingList) { for (final FieldToContractInputMapping mapping : mappingList) { checkedElements.add(mapping); checkAllMappings(checkedElements, mapping.getChildren()); } } }