org.drools.guvnor.client.decisiontable.ActionSetFieldPopup.java Source code

Java tutorial

Introduction

Here is the source code for org.drools.guvnor.client.decisiontable.ActionSetFieldPopup.java

Source

/*
 * Copyright 2011 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.guvnor.client.decisiontable;

import java.util.Arrays;
import java.util.List;

import com.google.gwt.user.client.ui.*;
import org.drools.guvnor.client.common.FormStylePopup;
import org.drools.guvnor.client.common.ImageButton;
import org.drools.guvnor.client.common.InfoPopup;
import org.drools.guvnor.client.common.SmallLabel;
import org.drools.guvnor.client.decisiontable.widget.DTCellValueUtilities;
import org.drools.guvnor.client.messages.Constants;
import org.drools.guvnor.client.resources.DroolsGuvnorImages;
import org.drools.guvnor.client.resources.GuvnorImages;
import org.drools.ide.common.client.modeldriven.SuggestionCompletionEngine;
import org.drools.ide.common.client.modeldriven.dt52.ActionCol52;
import org.drools.ide.common.client.modeldriven.dt52.ActionSetFieldCol52;
import org.drools.ide.common.client.modeldriven.dt52.BRLRuleModel;
import org.drools.ide.common.client.modeldriven.dt52.DTCellValue52;
import org.drools.ide.common.client.modeldriven.dt52.DTDataTypes52;
import org.drools.ide.common.client.modeldriven.dt52.GuidedDecisionTable52;
import org.drools.ide.common.client.modeldriven.dt52.GuidedDecisionTable52.TableFormat;
import org.drools.ide.common.client.modeldriven.dt52.LimitedEntryActionSetFieldCol52;
import org.drools.ide.common.client.modeldriven.dt52.LimitedEntryCol;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
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.user.client.Window;

public class ActionSetFieldPopup extends FormStylePopup {

    private SmallLabel bindingLabel = new SmallLabel();
    private TextBox fieldLabel = getFieldLabel();
    private SimplePanel limitedEntryValueWidgetContainer = new SimplePanel();
    private int limitedEntryValueAttributeIndex = -1;
    private TextBox valueListWidget = null;
    private SimplePanel defaultValueWidgetContainer = new SimplePanel();
    private int defaultValueWidgetContainerIndex = -1;

    private final GuidedDecisionTable52 model;
    private final SuggestionCompletionEngine sce;
    private final DTCellValueWidgetFactory factory;
    private final BRLRuleModel rm;
    private final DTCellValueUtilities utilities;

    private ActionSetFieldCol52 editingCol;

    private final boolean isReadOnly;

    public ActionSetFieldPopup(final SuggestionCompletionEngine sce, final GuidedDecisionTable52 model,
            final GenericColumnCommand refreshGrid, final ActionSetFieldCol52 col, final boolean isNew,
            final boolean isReadOnly) {
        this.rm = new BRLRuleModel(model);
        this.editingCol = cloneActionSetColumn(col);
        this.model = model;
        this.sce = sce;
        this.isReadOnly = isReadOnly;
        this.utilities = new DTCellValueUtilities(model, sce);

        //Set-up a factory for value editors
        factory = DTCellValueWidgetFactory.getInstance(model, sce, isReadOnly, allowEmptyValues());

        setTitle(Constants.INSTANCE.ColumnConfigurationSetAFieldOnAFact());
        setModal(false);

        //Fact on which field will be set
        HorizontalPanel pattern = new HorizontalPanel();
        pattern.add(bindingLabel);
        doBindingLabel();

        ImageButton changePattern = new ImageButton(createEnabledEditButton(), createDisabledEditButton(),
                Constants.INSTANCE.ChooseABoundFactThatThisColumnPertainsTo(), new ClickHandler() {
                    public void onClick(ClickEvent w) {
                        showChangeFact(w);
                    }
                });
        changePattern.setEnabled(!isReadOnly);
        pattern.add(changePattern);
        addAttribute(Constants.INSTANCE.Fact(), pattern);

        //Fact Field being set
        HorizontalPanel field = new HorizontalPanel();
        fieldLabel.setEnabled(!isReadOnly);
        field.add(fieldLabel);
        ImageButton editField = new ImageButton(createEnabledEditButton(), createDisabledEditButton(),
                Constants.INSTANCE.EditTheFieldThatThisColumnOperatesOn(), new ClickHandler() {
                    public void onClick(ClickEvent w) {
                        showFieldChange();
                    }
                });
        editField.setEnabled(!isReadOnly);
        field.add(editField);
        addAttribute(Constants.INSTANCE.Field(), field);
        doFieldLabel();

        //Column header
        final TextBox header = new TextBox();
        header.setText(col.getHeader());
        header.setEnabled(!isReadOnly);
        if (!isReadOnly) {
            header.addChangeHandler(new ChangeHandler() {
                public void onChange(ChangeEvent event) {
                    editingCol.setHeader(header.getText());
                }
            });
        }
        addAttribute(Constants.INSTANCE.ColumnHeaderDescription(), header);

        //Optional value list
        if (model.getTableFormat() == TableFormat.EXTENDED_ENTRY) {
            valueListWidget = new TextBox();
            valueListWidget.setText(editingCol.getValueList());
            valueListWidget.setEnabled(!isReadOnly);
            if (!isReadOnly) {

                //Copy value back to model
                valueListWidget.addChangeHandler(new ChangeHandler() {
                    public void onChange(ChangeEvent event) {
                        editingCol.setValueList(valueListWidget.getText());
                    }
                });

                //Update Default Value widget if necessary
                valueListWidget.addBlurHandler(new BlurHandler() {
                    public void onBlur(BlurEvent event) {
                        assertDefaultValue();
                        makeDefaultValueWidget();
                    }

                    private void assertDefaultValue() {
                        final List<String> valueList = Arrays.asList(model.getValueList(editingCol));
                        if (valueList.size() > 0) {
                            final String defaultValue = utilities.asString(editingCol.getDefaultValue());
                            if (!valueList.contains(defaultValue)) {
                                editingCol.getDefaultValue().clearValues();
                            }
                        } else {
                            //Ensure the Default Value has been updated to represent the column's data-type.
                            final DTCellValue52 defaultValue = editingCol.getDefaultValue();
                            final DTDataTypes52 dataType = utilities.getDataType(editingCol);
                            utilities.assertDTCellValue(dataType, defaultValue);
                        }
                    }

                });

            }
            HorizontalPanel vl = new HorizontalPanel();
            vl.add(valueListWidget);
            vl.add(new InfoPopup(Constants.INSTANCE.ValueList(), Constants.INSTANCE.ValueListsExplanation()));
            addAttribute(Constants.INSTANCE.optionalValueList(), vl);
        }
        doValueList();

        //Default Value
        if (model.getTableFormat() == TableFormat.EXTENDED_ENTRY) {
            defaultValueWidgetContainerIndex = addAttribute(Constants.INSTANCE.DefaultValue(),
                    defaultValueWidgetContainer);
            makeDefaultValueWidget();
        }

        //Limited entry value widget
        if (model.getTableFormat() == TableFormat.LIMITED_ENTRY) {
            limitedEntryValueAttributeIndex = addAttribute(Constants.INSTANCE.LimitedEntryValue(),
                    limitedEntryValueWidgetContainer);
            makeLimitedValueWidget();
        }

        //Update Engine with changes
        addAttribute(Constants.INSTANCE.UpdateEngineWithChanges(), doUpdate());

        //Hide column tick-box
        addAttribute(Constants.INSTANCE.HideThisColumn(),
                DTCellValueWidgetFactory.getHideColumnIndicator(editingCol));

        Button apply = new Button(Constants.INSTANCE.ApplyChanges());
        apply.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent w) {
                if (!isValidFactType()) {
                    Window.alert(Constants.INSTANCE.YouMustEnterAColumnFact());
                    return;
                }
                if (!isValidFactField()) {
                    Window.alert(Constants.INSTANCE.YouMustEnterAColumnField());
                    return;
                }
                if (null == editingCol.getHeader() || "".equals(editingCol.getHeader())) {
                    Window.alert(Constants.INSTANCE.YouMustEnterAColumnHeaderValueDescription());
                    return;
                }

                if (isNew) {
                    if (!unique(editingCol.getHeader())) {
                        Window.alert(Constants.INSTANCE.ThatColumnNameIsAlreadyInUsePleasePickAnother());
                        return;
                    }

                } else {
                    if (!col.getHeader().equals(editingCol.getHeader())) {
                        if (!unique(editingCol.getHeader())) {
                            Window.alert(Constants.INSTANCE.ThatColumnNameIsAlreadyInUsePleasePickAnother());
                            return;
                        }
                    }
                }

                // Pass new\modified column back for handling
                refreshGrid.execute(editingCol);
                hide();
            }
        });
        addAttribute("", apply);

    }

    private Image createDisabledEditButton() {
        Image disabledChangePattern = DroolsGuvnorImages.INSTANCE.EditDisabled();
        disabledChangePattern.setAltText(Constants.INSTANCE.ChooseABoundFactThatThisColumnPertainsTo());
        return disabledChangePattern;
    }

    private Image createEnabledEditButton() {
        Image enabledChangePattern = GuvnorImages.INSTANCE.Edit();
        enabledChangePattern.setAltText(Constants.INSTANCE.ChooseABoundFactThatThisColumnPertainsTo());
        return enabledChangePattern;
    }

    private boolean allowEmptyValues() {
        return this.model.getTableFormat() == TableFormat.EXTENDED_ENTRY;
    }

    private ActionSetFieldCol52 cloneActionSetColumn(ActionSetFieldCol52 col) {
        ActionSetFieldCol52 clone = null;
        if (col instanceof LimitedEntryActionSetFieldCol52) {
            clone = new LimitedEntryActionSetFieldCol52();
            DTCellValue52 dcv = cloneLimitedEntryValue(((LimitedEntryCol) col).getValue());
            ((LimitedEntryCol) clone).setValue(dcv);
        } else {
            clone = new ActionSetFieldCol52();
        }
        clone.setBoundName(col.getBoundName());
        clone.setFactField(col.getFactField());
        clone.setHeader(col.getHeader());
        clone.setType(col.getType());
        clone.setValueList(col.getValueList());
        clone.setUpdate(col.isUpdate());
        clone.setDefaultValue(new DTCellValue52(col.getDefaultValue()));
        clone.setHideColumn(col.isHideColumn());
        return clone;
    }

    private DTCellValue52 cloneLimitedEntryValue(DTCellValue52 dcv) {
        if (dcv == null) {
            return null;
        }
        DTCellValue52 clone = new DTCellValue52(dcv);
        return clone;
    }

    private void makeLimitedValueWidget() {
        if (!(editingCol instanceof LimitedEntryActionSetFieldCol52)) {
            return;
        }
        if (nil(editingCol.getFactField())) {
            setAttributeVisibility(limitedEntryValueAttributeIndex, false);
            return;
        }
        LimitedEntryActionSetFieldCol52 lea = (LimitedEntryActionSetFieldCol52) editingCol;
        setAttributeVisibility(limitedEntryValueAttributeIndex, true);
        if (lea.getValue() == null) {
            lea.setValue(factory.makeNewValue(editingCol));
        }
        limitedEntryValueWidgetContainer.setWidget(factory
                .getWidget(model.getConditionPattern(editingCol.getBoundName()), editingCol, lea.getValue()));
    }

    private void makeDefaultValueWidget() {
        if (model.getTableFormat() == TableFormat.LIMITED_ENTRY) {
            return;
        }
        if (nil(editingCol.getFactField())) {
            setAttributeVisibility(defaultValueWidgetContainerIndex, false);
            return;
        }
        setAttributeVisibility(defaultValueWidgetContainerIndex, true);
        if (editingCol.getDefaultValue() == null) {
            editingCol.setDefaultValue(factory.makeNewValue(editingCol));
        }

        //Ensure the Default Value has been updated to represent the column's 
        //data-type. Legacy Default Values are all String-based and need to be 
        //coerced to the correct type
        final DTCellValue52 defaultValue = editingCol.getDefaultValue();
        final DTDataTypes52 dataType = utilities.getDataType(editingCol);
        utilities.assertDTCellValue(dataType, defaultValue);
        defaultValueWidgetContainer.setWidget(
                factory.getWidget(model.getConditionPattern(editingCol.getBoundName()), editingCol, defaultValue));
    }

    private void doBindingLabel() {
        if (this.editingCol.getBoundName() != null) {
            this.bindingLabel.setText("" + this.editingCol.getBoundName());
        } else {
            this.bindingLabel.setText(Constants.INSTANCE.pleaseChooseABoundFactForThisColumn());
        }
    }

    private void doFieldLabel() {
        if (this.editingCol.getFactField() != null) {
            this.fieldLabel.setText(this.editingCol.getFactField());
        } else {
            this.fieldLabel.setText(Constants.INSTANCE.pleaseChooseAFactPatternFirst());
        }
    }

    private void doValueList() {
        if (model.getTableFormat() == TableFormat.LIMITED_ENTRY) {
            return;
        }

        //Don't show a Value List if either the Fact\Field is empty
        final String factType = model.getBoundFactType(editingCol.getBoundName());
        final String factField = editingCol.getFactField();
        boolean enableValueList = !((factType == null || "".equals(factType))
                || (factField == null || "".equals(factField)));

        //Don't show a Value List if the Fact\Field has an enumeration
        if (enableValueList) {
            enableValueList = !sce.hasEnums(factType, factField);
        }
        valueListWidget.setEnabled(enableValueList);
        if (!enableValueList) {
            valueListWidget.setText("");
        }
    }

    private Widget doUpdate() {
        HorizontalPanel hp = new HorizontalPanel();

        final CheckBox cb = new CheckBox();
        cb.setValue(editingCol.isUpdate());
        cb.setText("");
        cb.setEnabled(!isReadOnly);
        if (!isReadOnly) {
            cb.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent arg0) {
                    if (sce.isGlobalVariable(editingCol.getBoundName())) {
                        cb.setEnabled(false);
                        editingCol.setUpdate(false);
                    } else {
                        editingCol.setUpdate(cb.getValue());
                    }
                }
            });
        }
        hp.add(cb);
        hp.add(new InfoPopup(Constants.INSTANCE.UpdateFact(), Constants.INSTANCE.UpdateDescription()));
        return hp;
    }

    private String getFactType() {
        if (sce.isGlobalVariable(editingCol.getBoundName())) {
            return sce.getGlobalVariable(editingCol.getBoundName());
        }
        return getFactType(this.editingCol.getBoundName());
    }

    private String getFactType(String boundName) {
        return rm.getLHSBoundFact(boundName).getFactType();
    }

    private TextBox getFieldLabel() {
        final TextBox box = new TextBox();
        box.addChangeHandler(new ChangeHandler() {
            public void onChange(ChangeEvent event) {
                editingCol.setFactField(box.getText());
            }
        });
        return box;
    }

    private ListBox loadBoundFacts(String binding) {
        ListBox listBox = new ListBox();
        listBox.addItem(Constants.INSTANCE.Choose());
        List<String> factBindings = rm.getLHSBoundFacts();

        for (int index = 0; index < factBindings.size(); index++) {
            String boundName = factBindings.get(index);
            if (!"".equals(boundName)) {
                listBox.addItem(boundName);
                if (boundName.equals(binding)) {
                    listBox.setSelectedIndex(index + 1);
                }
            }
        }

        String[] globs = this.sce.getGlobalVariables();
        for (int i = 0; i < globs.length; i++) {
            listBox.addItem(globs[i]);
        }

        listBox.setEnabled(listBox.getItemCount() > 1);
        if (listBox.getItemCount() == 1) {
            listBox.clear();
            listBox.addItem(Constants.INSTANCE.NoPatternBindingsAvailable());
        }

        return listBox;
    }

    private boolean nil(String s) {
        return s == null || s.equals("");
    }

    private void showChangeFact(ClickEvent w) {
        final FormStylePopup pop = new FormStylePopup();

        final ListBox pats = this.loadBoundFacts(editingCol.getBoundName());
        pop.addAttribute(Constants.INSTANCE.ChooseFact(), pats);
        Button ok = new Button(Constants.INSTANCE.OK());
        pop.addAttribute("", ok);

        ok.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent w) {
                String val = pats.getValue(pats.getSelectedIndex());
                editingCol.setBoundName(val);
                editingCol.setFactField(null);
                makeLimitedValueWidget();
                makeDefaultValueWidget();
                doBindingLabel();
                doFieldLabel();
                doValueList();
                pop.hide();
            }
        });

        pop.show();

    }

    private void showFieldChange() {
        final FormStylePopup pop = new FormStylePopup();
        pop.setModal(false);

        final String factType = getFactType();
        String[] fields = this.sce.getFieldCompletions(factType);
        final ListBox box = new ListBox();
        for (int i = 0; i < fields.length; i++) {
            box.addItem(fields[i]);
        }
        pop.addAttribute(Constants.INSTANCE.Field(), box);
        Button b = new Button(Constants.INSTANCE.OK());
        pop.addAttribute("", b);
        b.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent w) {
                editingCol.setFactField(box.getItemText(box.getSelectedIndex()));
                editingCol.setType(sce.getFieldType(factType, editingCol.getFactField()));
                makeLimitedValueWidget();
                makeDefaultValueWidget();
                doFieldLabel();
                doValueList();
                pop.hide();
            }
        });
        pop.show();

    }

    private boolean isValidFactType() {
        return !(editingCol.getBoundName() == null || "".equals(editingCol.getBoundName()));
    }

    private boolean isValidFactField() {
        return !(editingCol.getFactField() == null || "".equals(editingCol.getFactField()));
    }

    private boolean unique(String header) {
        for (ActionCol52 o : model.getActionCols()) {
            if (o.getHeader().equals(header))
                return false;
        }
        return true;
    }

}