Java tutorial
/** * Copyright (C) 2009 BonitaSoft S.A. * BonitaSoft, 31 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.properties.sections.general; import java.util.List; import org.bonitasoft.studio.common.ExpressionConstants; import org.bonitasoft.studio.common.properties.ExtensibleGridPropertySection; import org.bonitasoft.studio.common.properties.IExtensibleGridPropertySectionContribution; import org.bonitasoft.studio.condition.ui.expression.ComparisonExpressionValidator; import org.bonitasoft.studio.decision.ui.DecisionTableWizard; import org.bonitasoft.studio.decision.ui.condition.MaximizableWizardDialog; import org.bonitasoft.studio.decision.ui.condition.TakeTransitionLabelProvider; import org.bonitasoft.studio.expression.editor.filter.AvailableExpressionTypeFilter; import org.bonitasoft.studio.expression.editor.viewer.ExpressionViewer; import org.bonitasoft.studio.model.expression.Expression; import org.bonitasoft.studio.model.expression.ExpressionFactory; import org.bonitasoft.studio.model.process.ANDGateway; import org.bonitasoft.studio.model.process.BoundaryEvent; import org.bonitasoft.studio.model.process.CatchLinkEvent; import org.bonitasoft.studio.model.process.Connection; import org.bonitasoft.studio.model.process.ProcessPackage; import org.bonitasoft.studio.model.process.SequenceFlow; import org.bonitasoft.studio.model.process.SequenceFlowConditionType; import org.bonitasoft.studio.model.process.SourceElement; import org.bonitasoft.studio.model.process.TargetElement; import org.bonitasoft.studio.model.process.XORGateway; import org.bonitasoft.studio.model.process.decision.DecisionTable; import org.bonitasoft.studio.model.process.decision.DecisionTableAction; import org.bonitasoft.studio.model.process.decision.DecisionTableLine; import org.bonitasoft.studio.model.process.decision.transitions.TakeTransitionAction; import org.bonitasoft.studio.model.process.decision.transitions.TransitionsFactory; import org.bonitasoft.studio.pics.Pics; import org.bonitasoft.studio.pics.PicsConstants; import org.bonitasoft.studio.profiles.manager.BonitaProfilesManager; import org.bonitasoft.studio.profiles.manager.IBonitaActivitiesCategory; import org.bonitasoft.studio.properties.i18n.Messages; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.conversion.IConverter; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.databinding.EMFDataBindingContext; import org.eclipse.emf.databinding.edit.EMFEditObservables; import org.eclipse.emf.databinding.edit.EMFEditProperties; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.viewers.ViewerProperties; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.RowLayoutFactory; import org.eclipse.jface.viewers.IElementComparer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; 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.ui.forms.widgets.Section; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; /** * @author Mickael Istria * @author Aurelien Pupier * @author Romain Bioteau */ public class TransitionCondition implements IExtensibleGridPropertySectionContribution { private TransactionalEditingDomain editingDomain; private SequenceFlow transition; private ExpressionViewer conditionViewer; private Color color; private Button defaultCheckBox; private EMFDataBindingContext dataBindingContext; private Button useExpressionCondition; private Button useDecisionTable; private TabbedPropertySheetWidgetFactory widgetFactory; private Section conditionSection; private Button updateTableButton; @Override public void createControl(final Composite mainComposite, final TabbedPropertySheetWidgetFactory widgetFactory, ExtensibleGridPropertySection extensibleGridPropertySection) { this.widgetFactory = widgetFactory; mainComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 5).create()); mainComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); defaultCheckBox = widgetFactory.createButton(mainComposite, Messages.defaultFlowLabel, SWT.CHECK); defaultCheckBox.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); final Composite radioComposite = widgetFactory.createComposite(mainComposite); radioComposite.setLayoutData( GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).create()); radioComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).create()); useExpressionCondition = widgetFactory.createButton(radioComposite, Messages.useExpression, SWT.RADIO); useDecisionTable = widgetFactory.createButton(radioComposite, Messages.useDecisionTable, SWT.RADIO); conditionSection = widgetFactory.createSection(mainComposite, Section.NO_TITLE | Section.CLIENT_INDENT); conditionSection.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); conditionSection.setExpanded(true); if (transition.getConditionType() == SequenceFlowConditionType.EXPRESSION) { conditionSection.setClient(createExpressionComposite(conditionSection, widgetFactory)); } else { conditionSection.setClient(createDecisionTableComposite(conditionSection, widgetFactory)); } refreshBindings(); } protected Composite createExpressionComposite(final Composite parent, TabbedPropertySheetWidgetFactory widgetFactory) { final Composite client = widgetFactory.createComposite(parent); client.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).spacing(0, 0).create()); client.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); conditionViewer = new ExpressionViewer(client, SWT.BORDER, widgetFactory, editingDomain, ProcessPackage.Literals.SEQUENCE_FLOW__CONDITION); conditionViewer.setMessage(Messages.conditionExpresssionHelpMessage, IStatus.INFO); conditionViewer.addExpressionValidator(ExpressionConstants.CONDITION_TYPE, new ComparisonExpressionValidator()); conditionViewer .addFilter(new AvailableExpressionTypeFilter(new String[] { ExpressionConstants.CONSTANT_TYPE, ExpressionConstants.PARAMETER_TYPE, ExpressionConstants.SCRIPT_TYPE, ExpressionConstants.VARIABLE_TYPE, ExpressionConstants.CONDITION_TYPE })); if (transition.getCondition() == null) { Expression expression = ExpressionFactory.eINSTANCE.createExpression(); expression.setReturnType(Boolean.class.getName()); expression.setReturnTypeFixed(true); expression.setType(ExpressionConstants.CONDITION_TYPE); editingDomain.getCommandStack().execute(SetCommand.create(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__CONDITION, expression)); } conditionViewer.setContext(transition); conditionViewer.setInput(transition); conditionViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) .grab(false, false).hint(350, SWT.DEFAULT).create()); return client; } protected Composite createDecisionTableComposite(final Composite parent, TabbedPropertySheetWidgetFactory widgetFactory) { final Composite client = widgetFactory.createComposite(parent); client.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).create()); client.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); updateTableButton = widgetFactory.createButton(client, Messages.editDecisionTable, SWT.PUSH); updateTableButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DecisionTableWizard wizard = new DecisionTableWizard(transition, transition.getDecisionTable()); final TakeTransitionAction takeTransitionAction = TransitionsFactory.eINSTANCE .createTakeTransitionAction(); takeTransitionAction.setTakeTransition(true); final TakeTransitionAction dontTakeTransitionAction = TransitionsFactory.eINSTANCE .createTakeTransitionAction(); dontTakeTransitionAction.setTakeTransition(false); wizard.setAvailableLineActions( new DecisionTableAction[] { takeTransitionAction, dontTakeTransitionAction }); wizard.setAvailableTableActions( new DecisionTableAction[] { dontTakeTransitionAction, takeTransitionAction }); wizard.setActionsLabelProvider(new TakeTransitionLabelProvider()); wizard.setActionsComparer(new IElementComparer() { @Override public int hashCode(Object element) { return element.hashCode(); } @Override public boolean equals(Object a, Object b) { if (a instanceof TakeTransitionAction && b instanceof TakeTransitionAction) { return ((TakeTransitionAction) a).isTakeTransition() == ((TakeTransitionAction) b) .isTakeTransition(); } else { return a.equals(b); } } }); WizardDialog dialog = new MaximizableWizardDialog(Display.getDefault().getActiveShell(), wizard); if (dialog.open() == Dialog.OK) { DecisionTable table = wizard.getDecisionTable(); CompoundCommand cmd = new CompoundCommand(); cmd.append(new SetCommand(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__DECISION_TABLE, table)); editingDomain.getCommandStack().execute(cmd); conditionSection.getClient().dispose(); conditionSection.setClient( createDecisionTableComposite(conditionSection, TransitionCondition.this.widgetFactory)); conditionSection.setExpanded(true); } } }); final Composite tableComposite = widgetFactory.createComposite(client); tableComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); tableComposite .setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).spacing(0, 3).create()); final DecisionTable table = transition.getDecisionTable(); if (table != null && !table.getLines().isEmpty()) { for (DecisionTableLine line : table.getLines()) { if (!line.getConditions().isEmpty()) { createLine(tableComposite, line.getConditions(), line.getAction()); } } } return client; } private void createLine(Composite parent, List<Expression> conditions, DecisionTableAction decisionTableAction) { final Composite row = widgetFactory.createComposite(parent); row.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); row.setLayout(RowLayoutFactory.fillDefaults().spacing(0).type(SWT.HORIZONTAL).create()); for (Expression condition : conditions) { widgetFactory.createLabel(row, condition.getContent(), SWT.NONE); if (conditions.indexOf(condition) != conditions.size() - 1) { widgetFactory.createLabel(row, " ", SWT.NONE); widgetFactory.createLabel(row, Messages.and, SWT.NONE); widgetFactory.createLabel(row, " ", SWT.NONE); } } widgetFactory.createLabel(row, " ", SWT.NONE); final Label image = widgetFactory.createLabel(row, "", SWT.NONE); image.setImage(Pics.getImage(PicsConstants.arrowRight)); if (decisionTableAction instanceof TakeTransitionAction) { if (((TakeTransitionAction) decisionTableAction).isTakeTransition()) { widgetFactory.createLabel(row, " ", SWT.NONE); widgetFactory.createLabel(row, Messages.takeTransition, SWT.NONE); } else { widgetFactory.createLabel(row, " ", SWT.NONE); widgetFactory.createLabel(row, Messages.dontTakeTransition, SWT.NONE); } } } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution#getLabel() */ @Override public String getLabel() { return Messages.connectionConnection; } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution * #isRelevantFor(org.eclipse.emf.ecore.EObject) */ @Override public boolean isRelevantFor(EObject eObject) { if (eObject instanceof SequenceFlow && BonitaProfilesManager.getInstance().isEnabled(IBonitaActivitiesCategory.DATA_MANAGEMENT)) { SourceElement source = ((SequenceFlow) eObject).getSource(); boolean sourceIdAndGateway = source instanceof ANDGateway; TargetElement target = ((SequenceFlow) eObject).getTarget(); boolean targetIsAndGateway = target instanceof ANDGateway && !(source instanceof XORGateway); return !(source instanceof BoundaryEvent) && !sourceIdAndGateway && !targetIsAndGateway; } return false; } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution#refresh() */ @Override public void refresh() { if (transition != null && !conditionSection.isDisposed()) { refreshBindings(); } } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution * #setEObject(org.eclipse.emf.ecore.EObject) */ @Override public void setEObject(EObject object) { transition = (SequenceFlow) object; } private void refreshBindings() { if (conditionSection != null && !conditionSection.isDisposed()) { if (dataBindingContext != null) { dataBindingContext.dispose(); } IConverter conditionConverter = new Converter(Boolean.class, Boolean.class) { @Override public Object convert(Object fromObject) { if (transition != null && transition.getSource() instanceof CatchLinkEvent) { return false; } return !(Boolean) fromObject; } }; IConverter defaultConverter = new Converter(Boolean.class, Boolean.class) { @Override public Object convert(Object fromObject) { if (transition != null && transition.getSource() instanceof CatchLinkEvent) { return false; } else { SourceElement elem = transition.getSource(); boolean alreadyExistDefault = false; for (Connection c : elem.getOutgoing()) { if (c instanceof SequenceFlow) { if (((SequenceFlow) c).isIsDefault() && !c.equals(transition)) { alreadyExistDefault = true; } } } if (alreadyExistDefault) { return false; } else { return true; } } } }; final UpdateValueStrategy useExpressionTargetToModel = new UpdateValueStrategy(); useExpressionTargetToModel.setConverter(new Converter(Boolean.class, SequenceFlowConditionType.class) { @Override public Object convert(Object fromObject) { if ((Boolean) fromObject) { return SequenceFlowConditionType.EXPRESSION; } else { return SequenceFlowConditionType.DECISION_TABLE; } } }); final UpdateValueStrategy useDescisionTargetToModel = new UpdateValueStrategy(); useDescisionTargetToModel.setConverter(new Converter(Boolean.class, SequenceFlowConditionType.class) { @Override public Object convert(Object fromObject) { if ((Boolean) fromObject) { return SequenceFlowConditionType.DECISION_TABLE; } else { return SequenceFlowConditionType.EXPRESSION; } } }); final UpdateValueStrategy useExpressionModelToTarget = new UpdateValueStrategy(); useExpressionModelToTarget.setConverter(new Converter(SequenceFlowConditionType.class, Boolean.class) { @Override public Object convert(Object fromObject) { if (fromObject == SequenceFlowConditionType.EXPRESSION) { return true; } else { return false; } } }); final UpdateValueStrategy useDecisionModelToTarget = new UpdateValueStrategy(); useDecisionModelToTarget.setConverter(new Converter(SequenceFlowConditionType.class, Boolean.class) { @Override public Object convert(Object fromObject) { if (fromObject == SequenceFlowConditionType.DECISION_TABLE) { return true; } else { return false; } } }); dataBindingContext = new EMFDataBindingContext(); IObservableValue typeValue = EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__CONDITION_TYPE); typeValue.addValueChangeListener(new IValueChangeListener() { @Override public void handleValueChange(ValueChangeEvent event) { if (conditionSection != null && !conditionSection.isDisposed()) { if (event.diff.getNewValue() == SequenceFlowConditionType.EXPRESSION && (conditionViewer == null || conditionViewer.getControl().isDisposed())) { if (conditionSection.getClient() != null) { conditionSection.getClient().dispose(); } conditionSection.setClient(createExpressionComposite(conditionSection, widgetFactory)); conditionSection.setExpanded(true); } else if (event.diff.getNewValue() == SequenceFlowConditionType.DECISION_TABLE && (conditionViewer != null && !conditionViewer.getControl().isDisposed())) { if (conditionSection.getClient() != null) { conditionSection.getClient().dispose(); } conditionSection .setClient(createDecisionTableComposite(conditionSection, widgetFactory)); conditionSection.setExpanded(true); } refreshBindings(); } } }); dataBindingContext.bindValue(SWTObservables.observeSelection(useExpressionCondition), typeValue, useExpressionTargetToModel, useExpressionModelToTarget); dataBindingContext.bindValue(SWTObservables.observeSelection(useDecisionTable), typeValue, useDescisionTargetToModel, useDecisionModelToTarget); dataBindingContext.bindValue(SWTObservables.observeSelection(defaultCheckBox), EMFEditObservables .observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT)); dataBindingContext.bindValue(SWTObservables.observeEnabled(defaultCheckBox), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(defaultConverter), new UpdateValueStrategy().setConverter(defaultConverter)); if (conditionViewer != null && !conditionViewer.getControl().isDisposed()) { dataBindingContext.bindValue(SWTObservables.observeEnabled(conditionViewer.getTextControl()), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(conditionConverter), new UpdateValueStrategy().setConverter(conditionConverter)); dataBindingContext.bindValue(SWTObservables.observeEnabled(conditionViewer.getToolbar()), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(conditionConverter), new UpdateValueStrategy().setConverter(conditionConverter)); conditionViewer.setEditingDomain(editingDomain); dataBindingContext.bindValue(ViewerProperties.singleSelection().observe(conditionViewer), EMFEditProperties.value(editingDomain, ProcessPackage.Literals.SEQUENCE_FLOW__CONDITION) .observe(transition)); conditionViewer.setInput(transition); dataBindingContext.bindValue(SWTObservables.observeSelection(useExpressionCondition), SWTObservables.observeEnabled(conditionViewer.getControl())); } dataBindingContext.bindValue(SWTObservables.observeEnabled(useExpressionCondition), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(conditionConverter), new UpdateValueStrategy().setConverter(conditionConverter)); dataBindingContext.bindValue(SWTObservables.observeEnabled(useDecisionTable), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(conditionConverter), new UpdateValueStrategy().setConverter(conditionConverter)); if (updateTableButton != null && !updateTableButton.isDisposed()) { dataBindingContext.bindValue(SWTObservables.observeEnabled(updateTableButton), EMFEditObservables.observeValue(editingDomain, transition, ProcessPackage.Literals.SEQUENCE_FLOW__IS_DEFAULT), new UpdateValueStrategy().setConverter(conditionConverter), new UpdateValueStrategy().setConverter(conditionConverter)); } } } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution * #setEditingDomain(org.eclipse.emf.transaction.TransactionalEditingDomain) */ @Override public void setEditingDomain(TransactionalEditingDomain editingDomain) { this.editingDomain = editingDomain; if (conditionViewer != null) { conditionViewer.setEditingDomain(editingDomain); } } /* * (non-Javadoc) * * @seeorg.bonitasoft.studio.properties.sections.general. * IExtenstibleGridPropertySectionContribution * #setSelection(org.eclipse.jface.viewers.ISelection) */ @Override public void setSelection(ISelection selection) { } /* (non-Javadoc) * @see org.bonitasoft.studio.common.properties.IExtensibleGridPropertySectionContribution#dispose() */ @Override public void dispose() { if (color != null && !color.isDisposed()) { color.dispose(); } if (dataBindingContext != null) { dataBindingContext.dispose(); } } }