Java tutorial
/* * Copyright 2012 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.workbench.screens.guided.rule.client.widget; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.ModelField; import org.drools.workbench.models.datamodel.oracle.OperatorsOracle; import org.drools.workbench.models.datamodel.rule.CompositeFieldConstraint; import org.drools.workbench.models.datamodel.rule.FactPattern; import org.drools.workbench.models.datamodel.rule.FieldConstraint; import org.drools.workbench.models.datamodel.rule.HasCEPWindow; import org.drools.workbench.models.datamodel.rule.HasConstraints; import org.drools.workbench.models.datamodel.rule.IPattern; import org.drools.workbench.models.datamodel.rule.RuleAttribute; import org.drools.workbench.models.datamodel.rule.RuleModel; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraintEBLeftSide; import org.drools.workbench.models.datamodel.rule.builder.DRLConstraintValueBuilder; import org.drools.workbench.models.datamodel.rule.visitors.ToStringExpressionVisitor; import org.drools.workbench.screens.guided.rule.client.editor.CEPOperatorsDropdown; import org.drools.workbench.screens.guided.rule.client.editor.CEPWindowOperatorsDropdown; import org.drools.workbench.screens.guided.rule.client.editor.ConstraintValueEditor; import org.drools.workbench.screens.guided.rule.client.editor.ExpressionTypeChangeEvent; import org.drools.workbench.screens.guided.rule.client.editor.ExpressionTypeChangeHandler; import org.drools.workbench.screens.guided.rule.client.editor.OperatorSelection; import org.drools.workbench.screens.guided.rule.client.editor.RuleModeller; import org.drools.workbench.screens.guided.rule.client.editor.factPattern.Connectives; import org.drools.workbench.screens.guided.rule.client.editor.factPattern.PopupCreator; import org.drools.workbench.screens.guided.rule.client.resources.GuidedRuleEditorResources; import org.drools.workbench.screens.guided.rule.client.resources.images.GuidedRuleEditorImages508; import org.kie.workbench.common.widgets.client.resources.HumanReadable; import org.kie.workbench.common.widgets.client.resources.i18n.HumanReadableConstants; import org.uberfire.client.callbacks.Callback; import org.uberfire.ext.widgets.common.client.common.ClickableLabel; import org.uberfire.ext.widgets.common.client.common.SmallLabel; /** * This is the new smart widget that works off the model. */ public class FactPatternWidget extends RuleModellerWidget { private FactPattern pattern; private FlexTable layout = new FlexTable(); private Connectives connectives; private PopupCreator popupCreator; private boolean bindable; private boolean isAll0WithLabel; private boolean readOnly; private boolean isFactTypeKnown; private final Map<SingleFieldConstraint, ConstraintValueEditor> constraintValueEditors = new HashMap<SingleFieldConstraint, ConstraintValueEditor>(); private ConstraintValueEditor constraintValueEditor; public FactPatternWidget(RuleModeller mod, EventBus eventBus, IPattern p, boolean canBind) { this(mod, eventBus, p, false, canBind, null); } /** * Creates a new FactPatternWidget * @param canBind * @param readOnly if the widget should be in RO mode. If this parameter is null, * the readOnly attribute is calculated. */ public FactPatternWidget(RuleModeller ruleModeller, EventBus eventBus, IPattern pattern, boolean canBind, Boolean readOnly) { this(ruleModeller, eventBus, pattern, false, canBind, readOnly); } public FactPatternWidget(RuleModeller mod, EventBus eventBus, IPattern p, boolean isAll0WithLabel, boolean canBind, Boolean readOnly) { super(mod, eventBus); this.pattern = (FactPattern) p; this.bindable = canBind; this.popupCreator = new PopupCreator(); this.popupCreator.setBindable(bindable); this.popupCreator.setDataModelOracle(mod.getDataModelOracle()); this.popupCreator.setModeller(mod); this.popupCreator.setPattern(pattern); this.isAll0WithLabel = isAll0WithLabel; //if readOnly == null, the RO attribute is calculated. this.isFactTypeKnown = mod.getDataModelOracle().isFactTypeRecognized(this.pattern.getFactType()); if (readOnly == null) { this.readOnly = !this.isFactTypeKnown; } else { this.readOnly = readOnly; } this.connectives = new Connectives(mod, eventBus, pattern, this.readOnly); layout.setWidget(0, 0, getPatternLabel(this.pattern)); FlexCellFormatter formatter = layout.getFlexCellFormatter(); formatter.setAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT, HasVerticalAlignment.ALIGN_BOTTOM); formatter.setStyleName(0, 0, "modeller-fact-TypeHeader"); List<FieldConstraint> sortedConst = sortConstraints(pattern.getFieldConstraints()); pattern.setFieldConstraints(sortedConst); drawConstraints(sortedConst, pattern); //CEP 'window' widget int row = layout.getRowCount() + 1; layout.setWidget(row, 0, createCEPWindowWidget(mod, pattern)); if (this.readOnly) { layout.addStyleName("editor-disabled-widget"); } initWidget(layout); } /** * Render a hierarchy of constraints, hierarchy here means constraints that * may themselves depend on members of constraint objects. With this code, * the GUI enables clicking rules of the form: $result = RoutingResult( * NerOption.types contains "arzt" ) * @param sortedConst a sorted list of constraints to display. */ private void drawConstraints(List<FieldConstraint> sortedConst, HasConstraints hasConstraints) { final FlexTable table = new FlexTable(); layout.setWidget(1, 0, table); List<FieldConstraint> parents = new ArrayList<FieldConstraint>(); for (int i = 0; i < sortedConst.size(); i++) { traverseSingleFieldConstraints(sortedConst, table, parents, hasConstraints, i); //now the clear icon final int currentRow = i; Image clear = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall(); clear.setTitle(GuidedRuleEditorResources.CONSTANTS.RemoveThisWholeRestriction()); clear.addClickHandler(createClickHandlerForClearImageButton(currentRow)); if (!this.readOnly) { //This used to be 5 and Connectives were not rendered table.setWidget(currentRow, 6, clear); } } } private ClickHandler createClickHandlerForClearImageButton(final int currentRow) { return new ClickHandler() { public void onClick(ClickEvent event) { if (Window.confirm(GuidedRuleEditorResources.CONSTANTS.RemoveThisItem())) { setModified(true); pattern.removeConstraint(currentRow); getModeller().refreshWidget(); } } }; } private void traverseSingleFieldConstraints(List<FieldConstraint> sortedConst, final FlexTable table, List<FieldConstraint> parents, HasConstraints hasConstraints, int i) { int tabs = -1; FieldConstraint current = sortedConst.get(i); if (current instanceof SingleFieldConstraint) { SingleFieldConstraint single = (SingleFieldConstraint) current; FieldConstraint parent = single.getParent(); for (int j = 0; j < parents.size(); j++) { FieldConstraint storedParent = parents.get(j); if (storedParent != null && storedParent.equals(parent)) { tabs = j + 1; traverseForRemoval(parents, j); parents.add(current); break; } } if (tabs < 0) { tabs = 0; parents.add(current); } } renderFieldConstraint(table, i, current, hasConstraints, true, tabs); } private void traverseForRemoval(List<FieldConstraint> parents, int j) { for (int k = j + 1; k < parents.size(); k++) { parents.remove(j + 1); } } /** * Sort the rule constraints such that parent rules are inserted directly * before their child rules. * @param constraints the list of inheriting constraints to sort. * @return a sorted list of constraints ready for display. */ private List<FieldConstraint> sortConstraints(FieldConstraint[] constraints) { List<FieldConstraint> sortedConst = new ArrayList<FieldConstraint>(constraints.length); for (int i = 0; i < constraints.length; i++) { FieldConstraint current = constraints[i]; if (current instanceof SingleFieldConstraint) { SingleFieldConstraint single = (SingleFieldConstraint) current; int index = sortedConst.indexOf(single.getParent()); if (single.getParent() == null) { sortedConst.add(single); } else if (index >= 0) { sortedConst.add(index + 1, single); } else { insertSingleFieldConstraint(single, sortedConst); } } else { sortedConst.add(current); } } return sortedConst; } /** * Recursively add constraints and their parents. * @param sortedConst the array to fill. * @param fieldConst the constraint to investigate. */ private void insertSingleFieldConstraint(SingleFieldConstraint fieldConst, List<FieldConstraint> sortedConst) { if (fieldConst.getParent() instanceof SingleFieldConstraint) { insertSingleFieldConstraint((SingleFieldConstraint) fieldConst.getParent(), sortedConst); } sortedConst.add(fieldConst); } /** * This will render a field constraint into the given table. The row is the * row number to stick it into. */ private void renderFieldConstraint(final FlexTable inner, int row, FieldConstraint constraint, HasConstraints hasConstraints, boolean showBinding, int tabs) { //if nesting, or predicate, then it will need to span 5 cols. if (constraint instanceof SingleFieldConstraint) { renderSingleFieldConstraint(inner, row, (SingleFieldConstraint) constraint, hasConstraints, showBinding, tabs); } else if (constraint instanceof CompositeFieldConstraint) { inner.setWidget(row, 1, compositeFieldConstraintEditor((CompositeFieldConstraint) constraint)); inner.getFlexCellFormatter().setColSpan(row, 1, 5); inner.setWidget(row, 0, new HTML(" ")); //NON-NLS } } /** * This will show the constraint editor - allowing field constraints to be * nested etc. */ private Widget compositeFieldConstraintEditor(final CompositeFieldConstraint constraint) { FlexTable t = new FlexTable(); String desc = null; ClickHandler click = new ClickHandler() { public void onClick(ClickEvent event) { popupCreator.showPatternPopupForComposite(constraint); } }; if (constraint.getCompositeJunctionType().equals(CompositeFieldConstraint.COMPOSITE_TYPE_AND)) { desc = GuidedRuleEditorResources.CONSTANTS.AllOf() + ":"; } else { desc = GuidedRuleEditorResources.CONSTANTS.AnyOf() + ":"; } t.setWidget(0, 0, new ClickableLabel(desc, click, !this.readOnly)); t.getFlexCellFormatter().setColSpan(0, 0, 2); FieldConstraint[] nested = constraint.getConstraints(); FlexTable inner = new FlexTable(); if (nested != null) { for (int i = 0; i < nested.length; i++) { this.renderFieldConstraint(inner, i, nested[i], constraint, true, 0); //add in remove icon here... final int currentRow = i; Image clear = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall(); clear.setTitle(GuidedRuleEditorResources.CONSTANTS.RemoveThisNestedRestriction()); clear.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { if (Window.confirm( GuidedRuleEditorResources.CONSTANTS.RemoveThisItemFromNestedConstraint())) { setModified(true); constraint.removeConstraint(currentRow); getModeller().refreshWidget(); } } }); if (!this.readOnly) { //This used to be 5 and Connectives were not rendered inner.setWidget(i, 6, clear); } } } t.setWidget(1, 1, inner); t.setWidget(1, 0, new HTML(" ")); return t; } /** * Applies a single field constraint to the given table, and start row. */ private void renderSingleFieldConstraint(final FlexTable inner, final int row, final SingleFieldConstraint constraint, final HasConstraints hasConstraints, boolean showBinding, final int tabs) { final int col = 1; //for offsetting, just a slight indent inner.setWidget(row, 0, new HTML(" ")); if (constraint.getConstraintValueType() != SingleFieldConstraint.TYPE_PREDICATE) { HorizontalPanel ebContainer = null; if (constraint instanceof SingleFieldConstraintEBLeftSide) { ebContainer = expressionBuilderLS((SingleFieldConstraintEBLeftSide) constraint, showBinding); inner.setWidget(row, 0 + col, ebContainer); } else { inner.setWidget(row, 0 + col, fieldLabel(constraint, hasConstraints, showBinding, tabs * 20)); } inner.setWidget(row, 1 + col, operatorDropDown(constraint, inner, row, 2 + col)); //Get first part of constraint.fieldName? #1=Fact1, #2=SubFact1 inner.setWidget(row, 2 + col, createValueEditor(constraint)); inner.setWidget(row, 3 + col, connectives.connectives(constraint)); if (ebContainer != null && ebContainer.getWidgetCount() > 0) { if (ebContainer.getWidget(0) instanceof ExpressionBuilder) { associateExpressionWithChangeHandler(inner, row, constraint, col, ebContainer); } } } else if (constraint.getConstraintValueType() == SingleFieldConstraint.TYPE_PREDICATE) { inner.setWidget(row, 1, predicateEditor(constraint)); inner.getFlexCellFormatter().setColSpan(row, 1, 5); } } //Widget for CEP 'windows' private Widget createCEPWindowWidget(final RuleModeller modeller, final HasCEPWindow c) { final HorizontalPanel hp = new HorizontalPanel(); modeller.getDataModelOracle().isFactTypeAnEvent(pattern.getFactType(), new Callback<Boolean>() { @Override public void callback(final Boolean result) { if (Boolean.TRUE.equals(result)) { final Label lbl = new Label(HumanReadableConstants.INSTANCE.OverCEPWindow()); lbl.setStyleName("paddedLabel"); hp.add(lbl); final CEPWindowOperatorsDropdown cwo = new CEPWindowOperatorsDropdown(c, readOnly); if (!isReadOnly()) { cwo.addValueChangeHandler(new ValueChangeHandler<OperatorSelection>() { public void onValueChange(ValueChangeEvent<OperatorSelection> event) { setModified(true); OperatorSelection selection = event.getValue(); String selected = selection.getValue(); c.getWindow().setOperator(selected); } }); } hp.add(cwo); } } }); return hp; } private void associateExpressionWithChangeHandler(final FlexTable inner, final int row, final SingleFieldConstraint constraint, final int col, HorizontalPanel ebContainer) { ExpressionBuilder eb = (ExpressionBuilder) ebContainer.getWidget(0); eb.addExpressionTypeChangeHandler(new ExpressionTypeChangeHandler() { public void onExpressionTypeChanged(ExpressionTypeChangeEvent event) { try { //Change "operator" drop-down as the content depends on data-type constraint.setFieldType(event.getNewType()); inner.setWidget(row, 1 + col, operatorDropDown(constraint, inner, row, 2 + col)); //Change "value" editor to the pen icon as the applicable Widget depends on data-type constraint.setConstraintValueType(SingleFieldConstraint.TYPE_UNDEFINED); constraint.setValue(""); inner.setWidget(row, 2 + col, createValueEditor(constraint)); } catch (Exception e) { e.printStackTrace(); } } }); } /** * This provides an inline formula editor, not unlike a spreadsheet does. */ private Widget predicateEditor(final SingleFieldConstraint c) { HorizontalPanel pred = new HorizontalPanel(); pred.setWidth("100%"); Image img = new Image(GuidedRuleEditorResources.INSTANCE.images().functionAssets()); img.setTitle(GuidedRuleEditorResources.CONSTANTS.FormulaBooleanTip()); pred.add(img); if (c.getValue() == null) { c.setValue(""); } final TextBox box = new TextBox(); box.setText(c.getValue()); if (!this.readOnly) { box.addChangeHandler(new ChangeHandler() { public void onChange(ChangeEvent event) { setModified(true); c.setValue(box.getText()); } }); box.setWidth("100%"); pred.add(box); } else { pred.add(new SmallLabel(c.getValue())); } return pred; } /** * This returns the pattern label. */ private Widget getPatternLabel(final FactPattern fp) { ClickHandler click = new ClickHandler() { public void onClick(ClickEvent event) { popupCreator.showPatternPopup(fp, null, false); } }; String patternName = (pattern.isBound()) ? pattern.getFactType() + " <b>[" + pattern.getBoundName() + "]</b>" : pattern.getFactType(); String desc; if (isAll0WithLabel) { desc = GuidedRuleEditorResources.CONSTANTS.All0with(patternName); } else { if (pattern.getNumberOfConstraints() > 0) { desc = GuidedRuleEditorResources.CONSTANTS.ThereIsAAn0With(patternName); } else { desc = GuidedRuleEditorResources.CONSTANTS.ThereIsAAn0(patternName); } desc = anA(desc, patternName); } return new ClickableLabel(desc, click, !this.readOnly); } /** * Change to an/a depending on context - only for english TODO use GWT * support for that: * http://code.google.com/intl/nl/webtoolkit/doc/latest/DevGuideI18n.html */ private String anA(String desc, String patternName) { if (desc.startsWith("There is a/an")) { //NON-NLS String vowel = patternName.substring(0, 1); if (vowel.equalsIgnoreCase("A") || vowel.equalsIgnoreCase("E") || vowel.equalsIgnoreCase("I") || vowel.equalsIgnoreCase("O") || vowel.equalsIgnoreCase("U")) { //NON-NLS return desc.replace("There is a/an", "There is an"); //NON-NLS } else { return desc.replace("There is a/an", "There is a"); //NON-NLS } } else { return desc; } } private Widget createValueEditor(final SingleFieldConstraint constraint) { constraintValueEditor = new ConstraintValueEditor(constraint, pattern.getConstraintList(), this.getModeller(), this.getEventBus(), this.readOnly); //If any literal value changes set to dirty and refresh dependent enumerations constraintValueEditor.setOnValueChangeCommand(new Command() { public void execute() { constraintValueEditor.hideError(); setModified(true); refreshConstraintValueEditorsDropDownData(constraint); } }); //If a Template Key value changes only set to dirty constraintValueEditor.setOnTemplateValueChangeCommand(new Command() { public void execute() { constraintValueEditor.hideError(); setModified(true); } }); //Keep a reference to the value editors so they can be refreshed for dependent enums constraintValueEditors.put(constraint, constraintValueEditor); return constraintValueEditor; } private Widget operatorDropDown(final SingleFieldConstraint constraint, final FlexTable inner, final int row, final int col) { final HorizontalPanel hp = new HorizontalPanel(); if (!this.readOnly) { getOperatorDropDown(constraint, inner, row, col, new Callback<CEPOperatorsDropdown>() { @Override public void callback(CEPOperatorsDropdown result) { hp.add(result); } }); } else { final SmallLabel sl = new SmallLabel( "<b>" + (constraint.getOperator() == null ? GuidedRuleEditorResources.CONSTANTS.pleaseChoose() : HumanReadable.getOperatorDisplayName(constraint.getOperator())) + "</b>"); hp.add(sl); } return hp; } private void getOperatorDropDown(final SingleFieldConstraint constraint, final FlexTable inner, final int row, final int col, final Callback<CEPOperatorsDropdown> callback) { String fieldName; String factType; //Connectives Operators are handled in class Connectives if (constraint instanceof SingleFieldConstraintEBLeftSide) { SingleFieldConstraintEBLeftSide sfexp = (SingleFieldConstraintEBLeftSide) constraint; factType = sfexp.getExpressionLeftSide().getPreviousClassType(); if (factType == null) { factType = sfexp.getExpressionLeftSide().getClassType(); } fieldName = sfexp.getExpressionLeftSide().getFieldName(); } else { factType = constraint.getFactType(); fieldName = constraint.getFieldName(); } getOperatorCompletions(constraint, inner, row, col, callback, fieldName, factType); } private void getOperatorCompletions(final SingleFieldConstraint constraint, final FlexTable inner, final int row, final int col, final Callback<CEPOperatorsDropdown> callback, String fieldName, String factType) { connectives.getDataModelOracle().getOperatorCompletions(factType, fieldName, new Callback<String[]>() { @Override public void callback(final String[] operators) { CEPOperatorsDropdown dropdown = new CEPOperatorsDropdown(operators, constraint); callback.callback(dropdown); dropdown.addValueChangeHandler(new ValueChangeHandler<OperatorSelection>() { public void onValueChange(ValueChangeEvent<OperatorSelection> event) { onDropDownValueChanged(event, constraint, inner, row, col); } }); } }); } private void onDropDownValueChanged(ValueChangeEvent<OperatorSelection> event, SingleFieldConstraint constraint, FlexTable inner, int row, int col) { setModified(true); final String selected = event.getValue().getValue(); final String selectedText = event.getValue().getDisplayText(); final String originalOperator = constraint.getOperator(); //Prevent recursion once operator change has been applied if (selectedText.equals(constraint.getOperator())) { return; } constraint.setOperator(selected); if (constraint.getOperator().equals("")) { constraint.setOperator(null); constraintValueEditor.hideError(); } else { constraintValueEditor.showError(); } if (inner != null) { if (isWidgetForValueNeeded(selectedText)) { inner.getWidget(row, col).setVisible(false); } else { inner.getWidget(row, col).setVisible(true); } } //If new operator requires a comma separated list and old did not, or vice-versa //we need to redraw the ConstraintValueEditor for the constraint if (OperatorsOracle.operatorRequiresList(selected) != OperatorsOracle .operatorRequiresList(originalOperator)) { if (OperatorsOracle.operatorRequiresList(selected) == false) { final String[] oldValueList = constraint.getValue().split(","); if (oldValueList.length > 0) { constraint.setValue(oldValueList[0]); } } //Redraw ConstraintValueEditor inner.setWidget(row, col, createValueEditor(constraint)); } } private boolean isWidgetForValueNeeded(String selectedText) { return selectedText.equals(HumanReadableConstants.INSTANCE.isEqualToNull()) || selectedText.equals(HumanReadableConstants.INSTANCE.isNotEqualToNull()); } private HorizontalPanel expressionBuilderLS(final SingleFieldConstraintEBLeftSide con, boolean showBinding) { HorizontalPanel ab = new HorizontalPanel(); ab.setStyleName("modeller-field-Label"); if (!con.isBound()) { if (bindable && showBinding && !this.readOnly) { ab.add(new ExpressionBuilder(getModeller(), getEventBus(), con.getExpressionLeftSide())); } else { final DRLConstraintValueBuilder constraintValueBuilder = DRLConstraintValueBuilder .getBuilder(getRuleDialect()); final ToStringExpressionVisitor visitor = new ToStringExpressionVisitor(constraintValueBuilder); ab.add(new SmallLabel(con.getExpressionLeftSide().getText(visitor))); } } else { ab.add(new ExpressionBuilder(getModeller(), getEventBus(), con.getExpressionLeftSide())); } return ab; } /** * get the field widget. This may be a simple label, or it may be bound (and * show the var name) or a icon to create a binding. It will only show the * binding option of showBinding is true. */ private Widget fieldLabel(final SingleFieldConstraint con, final HasConstraints hasConstraints, final boolean showBinding, final int padding) { HorizontalPanel ab = new HorizontalPanel(); ab.setStyleName("modeller-field-Label"); StringBuilder bindingLabel = new StringBuilder(); if (con.isBound()) { bindingLabel.append("<b>["); bindingLabel.append(con.getFieldBinding()); bindingLabel.append("]</b> "); } String fieldName = con.getFieldName(); bindingLabel.append(fieldName); if (bindable && showBinding && !this.readOnly) { ClickHandler click = new ClickHandler() { public void onClick(final ClickEvent event) { //If field name is "this" use parent FactPattern type otherwise we can use the Constraint's field type String fieldName = con.getFieldName(); if (DataType.TYPE_THIS.equals(fieldName)) { connectives.getDataModelOracle().getFieldCompletions(pattern.getFactType(), new Callback<ModelField[]>() { @Override public void callback(final ModelField[] fields) { popupCreator.showBindFieldPopup(pattern, con, fields, popupCreator); } }); } else { connectives.getDataModelOracle().getFieldCompletions(con.getFieldType(), new Callback<ModelField[]>() { @Override public void callback(final ModelField[] fields) { popupCreator.showBindFieldPopup(pattern, con, fields, popupCreator); } }); } } }; ClickableLabel cl = new ClickableLabel(bindingLabel.toString(), click, !this.readOnly); DOM.setStyleAttribute(cl.getElement(), "marginLeft", "" + padding + "pt"); ab.add(cl); } else { ab.add(new SmallLabel(bindingLabel.toString())); } return ab; } @Override public boolean isReadOnly() { return this.readOnly; } @Override public boolean isFactTypeKnown() { return this.isFactTypeKnown; } private void refreshConstraintValueEditorsDropDownData(final SingleFieldConstraint modifiedConstraint) { for (Map.Entry<SingleFieldConstraint, ConstraintValueEditor> e : constraintValueEditors.entrySet()) { final SingleFieldConstraint sfc = e.getKey(); if (sfc.getConstraintValueType() == SingleFieldConstraint.TYPE_LITERAL || sfc.getConstraintValueType() == SingleFieldConstraint.TYPE_ENUM) { if (!sfc.equals(modifiedConstraint)) { e.getValue().refreshEditor(); } } } } private String getRuleDialect() { final RuleModel model = getModeller().getModel(); for (int i = 0; i < model.attributes.length; i++) { RuleAttribute attr = model.attributes[i]; if (attr.getAttributeName().equals("dialect")) { return attr.getValue(); } } return DRLConstraintValueBuilder.DEFAULT_DIALECT; } }