Index: META-INF/MANIFEST.MF =================================================================== --- META-INF/MANIFEST.MF (revision 31372) +++ META-INF/MANIFEST.MF (working copy) @@ -2,7 +2,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %bundleName Bundle-SymbolicName: org.jbpm.gd.jpdl;singleton:=true -Bundle-Version: 3.3.0.qualifier +Bundle-Version: 3.4.0.qualifier Bundle-ClassPath: ., lib/dom4j-1.4.jar Bundle-Activator: org.jbpm.gd.jpdl.Plugin Index: src/org/jbpm/gd/jpdl/Plugin.java =================================================================== --- src/org/jbpm/gd/jpdl/Plugin.java (revision 31372) +++ src/org/jbpm/gd/jpdl/Plugin.java (working copy) @@ -33,6 +33,11 @@ private ResourceBundle resourceBundle; + /** + * @since 3.4 + */ + public static final String TRANS_COND_WARN_PREFERENCE = "transition condition warn"; + public Plugin() { super(); plugin = this; Index: src/org/jbpm/gd/jpdl/xml/ForkDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/ForkDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/ForkDomAdapter.java (working copy) @@ -10,6 +10,7 @@ import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.Fork; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Script; import org.jbpm.gd.jpdl.model.Timer; import org.jbpm.gd.jpdl.model.Transition; @@ -121,6 +122,7 @@ fork.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { fork.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("description".equals(getNodeType(type))) { fork.setDescription((Description)jpdlElement); } Index: src/org/jbpm/gd/jpdl/xml/TransitionDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/TransitionDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/TransitionDomAdapter.java (working copy) @@ -13,6 +13,7 @@ import org.jbpm.gd.jpdl.model.Description; import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.MailAction; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Script; import org.jbpm.gd.jpdl.model.Transition; @@ -86,6 +87,8 @@ transition.setTo(newValue); } else if ("name".equals(name)) { transition.setName(newValue); + } else if ("condition".equals(name)) { + transition.setName(newValue); } } Index: src/org/jbpm/gd/jpdl/xml/NodeDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/NodeDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/NodeDomAdapter.java (working copy) @@ -14,6 +14,7 @@ import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.MailAction; import org.jbpm.gd.jpdl.model.Node; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Script; import org.jbpm.gd.jpdl.model.Timer; import org.jbpm.gd.jpdl.model.Transition; @@ -149,6 +150,7 @@ node.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { node.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } } Index: src/org/jbpm/gd/jpdl/xml/SubProcessDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/SubProcessDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/SubProcessDomAdapter.java (working copy) @@ -4,7 +4,10 @@ import org.jbpm.gd.common.model.SemanticElement; import org.jbpm.gd.common.xml.XmlAdapter; +import org.jbpm.gd.jpdl.model.Fork; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.SubProcess; +import org.jbpm.gd.jpdl.model.Transition; public class SubProcessDomAdapter extends XmlAdapter { Index: src/org/jbpm/gd/jpdl/xml/ProcessStateDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/ProcessStateDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/ProcessStateDomAdapter.java (working copy) @@ -9,6 +9,7 @@ import org.jbpm.gd.jpdl.model.Description; import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.ProcessState; import org.jbpm.gd.jpdl.model.SubProcess; import org.jbpm.gd.jpdl.model.Timer; @@ -124,6 +125,7 @@ processState.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { processState.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("variable".equals(type)) { processState.addVariable((Variable)jpdlElement); } else if ("sub-process".equals(type)) { Index: src/org/jbpm/gd/jpdl/xml/TaskNodeDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/TaskNodeDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/TaskNodeDomAdapter.java (working copy) @@ -9,6 +9,7 @@ import org.jbpm.gd.jpdl.model.Description; import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Task; import org.jbpm.gd.jpdl.model.TaskNode; import org.jbpm.gd.jpdl.model.Timer; @@ -137,6 +138,7 @@ taskNode.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { taskNode.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("task".equals(type)) { taskNode.addTask((Task)jpdlElement); } else if ("description".equals(getNodeType(type))) { Index: src/org/jbpm/gd/jpdl/xml/StateDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/StateDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/StateDomAdapter.java (working copy) @@ -9,6 +9,7 @@ import org.jbpm.gd.jpdl.model.Description; import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.State; import org.jbpm.gd.jpdl.model.Timer; import org.jbpm.gd.jpdl.model.Transition; @@ -112,6 +113,7 @@ state.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { state.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("description".equals(getNodeType(type))) { state.setDescription((Description)jpdlElement); } Index: src/org/jbpm/gd/jpdl/xml/SuperStateDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/SuperStateDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/SuperStateDomAdapter.java (working copy) @@ -15,6 +15,7 @@ import org.jbpm.gd.jpdl.model.Join; import org.jbpm.gd.jpdl.model.MailNode; import org.jbpm.gd.jpdl.model.Node; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.ProcessState; import org.jbpm.gd.jpdl.model.State; import org.jbpm.gd.jpdl.model.SuperState; @@ -136,6 +137,7 @@ superState.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { superState.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("node".equals(type)) { superState.addNodeElement((Node)jpdlElement); } else if ("state".equals(type)) { Index: src/org/jbpm/gd/jpdl/xml/JoinDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/JoinDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/JoinDomAdapter.java (working copy) @@ -10,6 +10,7 @@ import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.Join; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Timer; import org.jbpm.gd.jpdl.model.Transition; @@ -111,6 +112,7 @@ join.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { join.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("description".equals(getNodeType(type))) { join.setDescription((Description)jpdlElement); } Index: src/org/jbpm/gd/jpdl/xml/MailNodeDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/MailNodeDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/MailNodeDomAdapter.java (working copy) @@ -10,6 +10,7 @@ import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.MailNode; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Subject; import org.jbpm.gd.jpdl.model.Text; import org.jbpm.gd.jpdl.model.Timer; @@ -148,6 +149,7 @@ mailNode.addTimer((Timer)jpdlElement); } else if ("transition".equals(type)) { mailNode.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("description".equals(getNodeType(type))) { mailNode.setDescription((Description)jpdlElement); } Index: src/org/jbpm/gd/jpdl/xml/StartStateDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/StartStateDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/StartStateDomAdapter.java (working copy) @@ -9,6 +9,7 @@ import org.jbpm.gd.jpdl.model.Description; import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.StartState; import org.jbpm.gd.jpdl.model.Task; import org.jbpm.gd.jpdl.model.Transition; @@ -96,6 +97,7 @@ startState.setDescription((Description)jpdlElement); } else if ("transition".equals(type)) { startState.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } else if ("event".equals(type)) { startState.addEvent((Event)jpdlElement); } else if ("exception-handler".equals(type)) { Index: src/org/jbpm/gd/jpdl/xml/DecisionDomAdapter.java =================================================================== --- src/org/jbpm/gd/jpdl/xml/DecisionDomAdapter.java (revision 31246) +++ src/org/jbpm/gd/jpdl/xml/DecisionDomAdapter.java (working copy) @@ -11,6 +11,7 @@ import org.jbpm.gd.jpdl.model.Event; import org.jbpm.gd.jpdl.model.ExceptionHandler; import org.jbpm.gd.jpdl.model.Handler; +import org.jbpm.gd.jpdl.model.NodeElement; import org.jbpm.gd.jpdl.model.Transition; public class DecisionDomAdapter extends XmlAdapter { @@ -120,6 +121,7 @@ decision.addExceptionHandler((ExceptionHandler)jpdlElement); } else if ("transition".equals(type)) { decision.addTransition((Transition)jpdlElement); + ((Transition)jpdlElement).setSource((NodeElement)getSemanticElement()); } } Index: src/org/jbpm/gd/jpdl/prefs/CompatibilityPage.java =================================================================== --- src/org/jbpm/gd/jpdl/prefs/CompatibilityPage.java (revision 0) +++ src/org/jbpm/gd/jpdl/prefs/CompatibilityPage.java (revision 0) @@ -0,0 +1,79 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jbpm.gd.jpdl.prefs; + +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.jbpm.gd.jpdl.Constants; +import org.jbpm.gd.jpdl.Plugin; + +/** + * @since 3.4 + */ +public class CompatibilityPage extends PreferencePage implements IWorkbenchPreferencePage, Constants { + + private Button transCondWarningButton; + + protected Control createContents(Composite parent) { + Composite clientArea = createClientArea(parent); + createIncludeXsdButton(clientArea); + return null; + } + + private void createIncludeXsdButton(Composite parent) { + transCondWarningButton = new Button(parent, SWT.CHECK); + transCondWarningButton.setText("Suppress warning on invalid transitions with conditions." ); + transCondWarningButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + transCondWarningButton.setSelection(getPreferenceStore().getBoolean(Plugin.TRANS_COND_WARN_PREFERENCE)); + } + + private Composite createClientArea(Composite parent) { + Composite clientArea = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + clientArea.setLayout(layout); + GridData gridData = new GridData(GridData.FILL_BOTH); + clientArea.setLayoutData(gridData); + return clientArea; + } + + public void init(IWorkbench workbench) { + setPreferenceStore(Plugin.getDefault().getPreferenceStore()); + } + + public void performDefaults() { + getPreferenceStore().setToDefault(Plugin.TRANS_COND_WARN_PREFERENCE); + } + + public boolean performOk() { + getPreferenceStore().setValue(Plugin.TRANS_COND_WARN_PREFERENCE, transCondWarningButton.getSelection()); + return true; + } + +} Index: src/org/jbpm/gd/jpdl/model/AbstractNode.java =================================================================== --- src/org/jbpm/gd/jpdl/model/AbstractNode.java (revision 31246) +++ src/org/jbpm/gd/jpdl/model/AbstractNode.java (working copy) @@ -59,6 +59,7 @@ public void removeTransition(Transition transition) { if (!(transitions.contains(transition))) return; transitions.remove(transition); + transition.setSource(null); firePropertyChange("transitionRemove", transition, null); } Index: src/org/jbpm/gd/jpdl/properties/ConditionSection.java =================================================================== --- src/org/jbpm/gd/jpdl/properties/ConditionSection.java (revision 31370) +++ src/org/jbpm/gd/jpdl/properties/ConditionSection.java (working copy) @@ -1,5 +1,8 @@ package org.jbpm.gd.jpdl.properties; +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; @@ -19,8 +22,11 @@ import org.jbpm.gd.common.part.NotationElementGraphicalEditPart; import org.jbpm.gd.common.part.OutlineEditPart; import org.jbpm.gd.common.properties.AbstractPropertySection; +import org.jbpm.gd.jpdl.Plugin; import org.jbpm.gd.jpdl.model.Condition; +import org.jbpm.gd.jpdl.model.Decision; import org.jbpm.gd.jpdl.model.Transition; +import org.jbpm.gd.jpdl.prefs.CompatibilityPage; public class ConditionSection extends AbstractPropertySection implements SelectionListener, FocusListener { @@ -31,18 +37,29 @@ private Text expressionText; private Text scriptText; private Transition transition; - + + private static final String CONDITION_ON_TRANSITION_WARNING = "Invalid condition: transitions with conditions only valid if the source node is a decision!"; + + private Label warningLabel; + private Boolean hideTransitionConditionWarnings; + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { super.createControls(parent, aTabbedPropertySheetPage); Composite clientArea = getWidgetFactory().createFlatFormComposite(parent); + + warningLabel = getWidgetFactory().createLabel(clientArea, ""); + warningLabel.setForeground(ColorConstants.red); conditionLabel = getWidgetFactory().createLabel(clientArea, "Condition Type"); conditionCombo = getWidgetFactory().createCCombo(clientArea); - conditionCombo.setItems(new String[] {"Unconditional", "Expression", "Script" }); + // updateConditionCombo(); -- refresh is always called, and the ConditionCombo is set there. + conditionCombo.setEditable(false); label = getWidgetFactory().createLabel(clientArea, ""); expressionText = getWidgetFactory().createText(clientArea, ""); scriptText = getWidgetFactory().createText(clientArea, "", SWT.H_SCROLL | SWT.V_SCROLL); + + warningLabel.setLayoutData(createWarningLabelLayoutData()); conditionLabel.setLayoutData(createConditionLabelLayoutData()); conditionCombo.setLayoutData(createConditionComboLayoutData()); label.setLayoutData(createLabelLayoutData()); @@ -51,15 +68,85 @@ hookListeners(); refresh(); } - + + IPropertyChangeListener preferenceListener = new IPropertyChangeListener() { + /* + * @see IPropertyChangeListener.propertyChange() + */ + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(Plugin.TRANS_COND_WARN_PREFERENCE)) { + hideTransitionConditionWarnings = null; + } + } + }; + private void hookListeners() { conditionCombo.addSelectionListener(this); expressionText.addSelectionListener(this); expressionText.addFocusListener(this); scriptText.addSelectionListener(this); scriptText.addFocusListener(this); + Plugin.getDefault().getPreferenceStore().addPropertyChangeListener(preferenceListener); } - + + public void dispose() { + Plugin.getDefault().getPreferenceStore().removePropertyChangeListener(preferenceListener); + super.dispose(); + } + + private void updateConditionCombo() { + if (transition == null) { + conditionCombo.setItems(new String[] { "Unconditional" }); + } + else if (getHideTransitionConditionWarning() ) { + conditionCombo.setItems(new String[] { "Unconditional", "Expression", "Script" }); + } + else { + // showTransitionConditionWarning && transition != null + if( transition.getSource() instanceof Decision ) { + conditionCombo.setItems(new String[] { "Unconditional", "Expression", "Script" }); + } + else if (transition.getCondition() != null ) { + // backwards compatibility, warning will be shown + if (transition.getCondition().getExpression() != null) { + conditionCombo.setItems(new String[] { "Unconditional", "Expression" }); + } + else if (transition.getCondition().getScript() != null) { + conditionCombo.setItems(new String[] { "Unconditional", "Script" }); + } + } + else { + conditionCombo.setItems(new String[] { "Unconditional" }); + } + } + } + + private void updateWarningLabel() { + if( getHideTransitionConditionWarning() ) { + warningLabel.setText(""); + } + else if (transition == null + || transition.getCondition() == null + || transition.getSource() == null + || transition.getSource() instanceof Decision) { + warningLabel.setText(""); + } + else if (transition.getCondition() != null && !(transition.getSource() instanceof Decision)) { + warningLabel.setText(CONDITION_ON_TRANSITION_WARNING); + } + else { + warningLabel.setText(""); + } + } + + private FormData createWarningLabelLayoutData() { + FormData result = new FormData(); + result.left = new FormAttachment(0, 5); + result.right = new FormAttachment(100, -5); + result.top = new FormAttachment(conditionCombo, 10); + return result; + } + private FormData createConditionLabelLayoutData() { FormData result = new FormData(); result.left = new FormAttachment(0, 5); @@ -78,7 +165,7 @@ FormData result = new FormData(); result.left = new FormAttachment(0, 5); result.right = new FormAttachment(100, -5); - result.top = new FormAttachment(conditionCombo, 10); + result.top = new FormAttachment(warningLabel, 10); return result; } @@ -116,6 +203,8 @@ } public void refresh() { + updateConditionCombo(); + updateWarningLabel(); if (transition == null || transition.getCondition() == null){ conditionCombo.setText("Unconditional"); label.setText(""); @@ -146,7 +235,7 @@ scriptText.setVisible(false); } } - } + } public boolean shouldUseExtraSpace() { return true; @@ -180,6 +269,7 @@ private void handleConditionComboSelected() { if ("Expression".equals(conditionCombo.getText())) { + updateWarningLabel(); label.setText("Expression"); scriptText.setVisible(false); expressionText.setVisible(true); @@ -187,6 +277,7 @@ updateCondition(); } } else if ("Script".equals(conditionCombo.getText())) { + updateWarningLabel(); label.setText("Script"); expressionText.setVisible(false); scriptText.setVisible(true); @@ -194,6 +285,7 @@ updateCondition(); } } else { + warningLabel.setText(""); label.setText(""); expressionText.setVisible(false); scriptText.setVisible(false); @@ -229,4 +321,12 @@ } } + private Boolean getHideTransitionConditionWarning() { + if (hideTransitionConditionWarnings == null) { + hideTransitionConditionWarnings = Plugin.getDefault().getPreferenceStore() + .getBoolean(Plugin.TRANS_COND_WARN_PREFERENCE); + } + return hideTransitionConditionWarnings; + } + } \ No newline at end of file Index: plugin.xml =================================================================== --- plugin.xml (revision 31246) +++ plugin.xml (working copy) @@ -379,6 +379,11 @@ id="org.jbpm.gd.jpdl.prefs.templates" name="Jpdl Templates" category="org.jbpm.gd.jpdl.prefs.jbpm3"/> +