Package org.drools.workbench.screens.guided.rule.client.editor

Source Code of org.drools.workbench.screens.guided.rule.client.editor.RuleModeller

/*
* 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.editor;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
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.Image;
import com.google.gwt.user.client.ui.Widget;
import org.drools.workbench.models.commons.shared.rule.IAction;
import org.drools.workbench.models.commons.shared.rule.IPattern;
import org.drools.workbench.models.commons.shared.rule.RuleMetadata;
import org.drools.workbench.models.commons.shared.rule.RuleModel;
import org.drools.workbench.screens.guided.rule.client.editor.events.TemplateVariablesChangedEvent;
import org.drools.workbench.screens.guided.rule.client.resources.i18n.Constants;
import org.drools.workbench.screens.guided.rule.client.resources.images.GuidedRuleEditorImages508;
import org.drools.workbench.screens.guided.rule.client.widget.RuleModellerWidget;
import org.guvnor.common.services.workingset.client.WorkingSetManager;
import org.kie.workbench.common.services.datamodel.oracle.PackageDataModelOracle;
import org.kie.workbench.common.services.security.UserCapabilities;
import org.kie.workbench.common.widgets.client.popups.errors.ErrorPopup;
import org.kie.workbench.common.widgets.client.resources.CommonAltedImages;
import org.uberfire.backend.vfs.Path;
import org.uberfire.client.common.ClickableLabel;
import org.uberfire.client.common.DirtyableComposite;
import org.uberfire.client.common.DirtyableFlexTable;
import org.uberfire.client.common.DirtyableHorizontalPane;
import org.uberfire.client.common.DirtyableVerticalPane;
import org.uberfire.client.common.SmallLabel;

/**
* This is the parent widget that contains the model based rule builder.
*/
public class RuleModeller extends DirtyableComposite
        implements
        RuleModelEditor {

    private WorkingSetManager workingSetManager = null;

    private DirtyableFlexTable layout;
    private RuleModel model;
    private PackageDataModelOracle dataModel;
    private RuleModellerConfiguration configuration;

    private boolean showingOptions = false;
    private int currentLayoutRow = 0;
    private Path path;
    private ModellerWidgetFactory widgetFactory;
    private EventBus eventBus;
    private boolean isReadOnly = false;
    private boolean isDSLEnabled = true;

    private List<RuleModellerWidget> lhsWidgets = new ArrayList<RuleModellerWidget>();
    private List<RuleModellerWidget> rhsWidgets = new ArrayList<RuleModellerWidget>();

    private boolean hasModifiedWidgets;

    private final Command onWidgetModifiedCommand = new Command() {

        public void execute() {
            hasModifiedWidgets = true;
        }
    };

    //used by Guided Rule (DRL + DSLR)
    public RuleModeller( final Path path,
                         final RuleModel model,
                         final PackageDataModelOracle dataModel,
                         final ModellerWidgetFactory widgetFactory,
                         final EventBus eventBus,
                         final boolean isReadOnly,
                         final boolean isDSLEnabled ) {
        this( path,
              model,
              dataModel,
              widgetFactory,
              RuleModellerConfiguration.getDefault(),
              eventBus,
              isReadOnly );
        this.isDSLEnabled = isDSLEnabled;
    }

    //used by Guided Templates
    public RuleModeller( final Path path,
                         final RuleModel model,
                         final PackageDataModelOracle dataModel,
                         final ModellerWidgetFactory widgetFactory,
                         final EventBus eventBus,
                         final boolean isReadOnly ) {
        this( path,
              model,
              dataModel,
              widgetFactory,
              eventBus,
              isReadOnly,
              true );
    }

    //used by Guided Decision BRL Fragments
    public RuleModeller( final Path path,
                         final RuleModel model,
                         final PackageDataModelOracle dataModel,
                         final ModellerWidgetFactory widgetFactory,
                         final RuleModellerConfiguration configuration,
                         final EventBus eventBus,
                         final boolean isReadOnly ) {
        this.path = path;
        this.model = model;
        this.dataModel = dataModel;
        this.widgetFactory = widgetFactory;
        this.configuration = configuration;
        this.eventBus = eventBus;
        this.isReadOnly = isReadOnly;

        doLayout();
    }

    protected void doLayout() {
        layout = new DirtyableFlexTable();
        initWidget();
        layout.setStyleName( "model-builder-Background" );
        initWidget( layout );
        setWidth( "100%" );
        setHeight( "100%" );
    }

    /**
     * This updates the widget to reflect the state of the model.
     */
    public void initWidget() {
        layout.removeAllRows();
        currentLayoutRow = 0;

        Image addPattern = GuidedRuleEditorImages508.INSTANCE.NewItem();
        addPattern.setTitle( Constants.INSTANCE.AddAConditionToThisRule() );
        addPattern.addClickHandler( new ClickHandler() {

            public void onClick( ClickEvent event ) {
                showConditionSelector( null );
            }
        } );

        layout.getColumnFormatter().setWidth( 0,
                                              "20px" );
        layout.getColumnFormatter().setWidth( 1,
                                              "20px" );
        layout.getColumnFormatter().setWidth( 2,
                                              "48px" );
        layout.getColumnFormatter().setWidth( 4,
                                              "64px" );

        if ( this.showLHS() ) {
            layout.setWidget( currentLayoutRow,
                              0,
                              new SmallLabel( "<b>" + Constants.INSTANCE.WHEN() + "</b>" ) );
            layout.getFlexCellFormatter().setColSpan( currentLayoutRow,
                                                      0,
                                                      4 );

            if ( !lockLHS() ) {
                layout.setWidget( currentLayoutRow,
                                  1,
                                  addPattern );
            }
            currentLayoutRow++;

            renderLhs( this.model );
        }

        if ( this.showRHS() ) {
            layout.setWidget( currentLayoutRow,
                              0,
                              new SmallLabel( "<b>" + Constants.INSTANCE.THEN() + "</b>" ) );
            layout.getFlexCellFormatter().setColSpan( currentLayoutRow,
                                                      0,
                                                      4 );

            Image addAction = GuidedRuleEditorImages508.INSTANCE.NewItem();
            addAction.setTitle( Constants.INSTANCE.AddAnActionToThisRule() );
            addAction.addClickHandler( new ClickHandler() {

                public void onClick( ClickEvent event ) {
                    showActionSelector( (Widget) event.getSource(),
                                        null );
                }
            } );
            if ( !lockRHS() ) {
                layout.setWidget( currentLayoutRow,
                                  1,
                                  addAction );
            }
            currentLayoutRow++;

            renderRhs( this.model );
        }

        if ( showAttributes() ) {

            final int optionsRowIndex = currentLayoutRow;
            if ( !this.showingOptions ) {
                ClickableLabel showMoreOptions = new ClickableLabel( "(show options...)",
                                                                     new ClickHandler() {

                                                                         public void onClick( ClickEvent event ) {
                                                                             showingOptions = true;
                                                                             renderOptions( optionsRowIndex );
                                                                         }
                                                                     } );
                layout.setWidget( optionsRowIndex,
                                  2,
                                  showMoreOptions );
            } else {
                renderOptions( optionsRowIndex );
            }

        }

        currentLayoutRow++;
        layout.setWidget( currentLayoutRow + 1,
                          3,
                          spacerWidget() );
        layout.getCellFormatter().setHeight( currentLayoutRow + 1,
                                             3,
                                             "100%" );
    }

    private void renderOptions( final int optionsRowIndex ) {
        layout.setWidget( optionsRowIndex,
                          2,
                          new SmallLabel( Constants.INSTANCE.optionsRuleModeller() ) );
        if ( !isReadOnly ) {
            layout.setWidget( optionsRowIndex,
                              4,
                              getAddAttribute() );
        }
        layout.setWidget( optionsRowIndex + 1,
                          3,
                          new RuleAttributeWidget( this,
                                                   this.model,
                                                   isReadOnly ) );
    }

    private boolean isLock( String attr ) {

        if ( isReadOnly() ) {
            return true;
        }

        if ( this.model.metadataList.length == 0 ) {
            return false;
        }

        for ( RuleMetadata at : this.model.metadataList ) {
            if ( at.getAttributeName().equals( attr ) ) {
                return true;
            }
        }
        return false;
    }

    public boolean showRHS() {
        return !this.configuration.isHideRHS();
    }

    /**
     * return true if we should not allow unfrozen editing of the RHS
     */
    public boolean lockRHS() {
        return isLock( RuleAttributeWidget.LOCK_RHS );
    }

    public boolean showLHS() {
        return !this.configuration.isHideLHS();
    }

    /**
     * return true if we should not allow unfrozen editing of the LHS
     */
    public boolean lockLHS() {
        return isLock( RuleAttributeWidget.LOCK_LHS );
    }

    private boolean showAttributes() {
        if ( !UserCapabilities.canSeeModulesTree() ) {
            return false;
        }

        return !this.configuration.isHideAttributes();
    }

    public void refreshWidget() {
        initWidget();
        makeDirty();
    }

    private Widget getAddAttribute() {
        Image add = GuidedRuleEditorImages508.INSTANCE.NewItem();
        add.setTitle( Constants.INSTANCE.AddAnOptionToTheRuleToModifyItsBehaviorWhenEvaluatedOrExecuted() );

        add.addClickHandler( new ClickHandler() {

            public void onClick( ClickEvent event ) {
                showAttributeSelector();
            }
        } );
        return add;
    }

    protected void showAttributeSelector() {
        AttributeSelectorPopup pop = new AttributeSelectorPopup( model,
                                                                 lockLHS(),
                                                                 lockRHS(),
                                                                 new Command() {

                                                                     public void execute() {
                                                                         refreshWidget();
                                                                     }
                                                                 } );

        pop.show();
    }

    /**
     * Do all the widgets for the RHS.
     */
    private void renderRhs( final RuleModel model ) {

        for ( int i = 0; i < model.rhs.length; i++ ) {
            DirtyableVerticalPane widget = new DirtyableVerticalPane();
            widget.setWidth( "100%" );
            IAction action = model.rhs[ i ];

            //if lockRHS() set the widget RO, otherwise let them decide.
            Boolean readOnly = this.lockRHS() ? true : null;

            RuleModellerWidget w = getWidgetFactory().getWidget( this,
                                                                 eventBus,
                                                                 action,
                                                                 readOnly );
            w.addOnModifiedCommand( this.onWidgetModifiedCommand );

            widget.add( wrapRHSWidget( model,
                                       i,
                                       w ) );
            widget.add( spacerWidget() );

            layout.setWidget( currentLayoutRow,
                              0,
                              new DirtyableHorizontalPane() );
            layout.setWidget( currentLayoutRow,
                              1,
                              new DirtyableHorizontalPane() );

            layout.setWidget( currentLayoutRow,
                              2,
                              this.wrapLineNumber( i + 1,
                                                   false ) );
            layout.getFlexCellFormatter().setHorizontalAlignment( currentLayoutRow,
                                                                  2,
                                                                  HasHorizontalAlignment.ALIGN_CENTER );
            layout.getFlexCellFormatter().setVerticalAlignment( currentLayoutRow,
                                                                2,
                                                                HasVerticalAlignment.ALIGN_MIDDLE );

            layout.setWidget( currentLayoutRow,
                              3,
                              widget );
            layout.getFlexCellFormatter().setHorizontalAlignment( currentLayoutRow,
                                                                  3,
                                                                  HasHorizontalAlignment.ALIGN_LEFT );
            layout.getFlexCellFormatter().setVerticalAlignment( currentLayoutRow,
                                                                3,
                                                                HasVerticalAlignment.ALIGN_TOP );
            layout.getFlexCellFormatter().setWidth( currentLayoutRow,
                                                    3,
                                                    "100%" );

            if ( !w.isFactTypeKnown() ) {
                final Image image = GuidedRuleEditorImages508.INSTANCE.Error();
                image.setTitle( Constants.INSTANCE.InvalidPatternSectionDisabled() );
                this.addLineIcon( currentLayoutRow,
                                  0,
                                  image );
            }

            final int index = i;
            if ( !( this.lockRHS() || w.isReadOnly() ) ) {
                this.addActionsButtonsToLayout( Constants.INSTANCE.AddAnActionBelow(),
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        showActionSelector( (Widget) event.getSource(),
                                                                            index + 1 );
                                                    }
                                                },
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        model.moveRhsItemDown( index );
                                                        refreshWidget();
                                                    }
                                                },
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        model.moveRhsItemUp( index );
                                                        refreshWidget();
                                                    }
                                                }
                                              );
            }

            this.rhsWidgets.add( w );
            currentLayoutRow++;

        }

    }

    /**
     * Pops up the fact selector.
     */
    protected void showConditionSelector( Integer position ) {
        RuleModellerConditionSelectorPopup popup = new RuleModellerConditionSelectorPopup( model,
                                                                                           this,
                                                                                           position,
                                                                                           getSuggestionCompletions() );
        popup.show();
    }

    protected void showActionSelector( Widget w,
                                       Integer position ) {
        RuleModellerActionSelectorPopup popup = new RuleModellerActionSelectorPopup( model,
                                                                                     this,
                                                                                     position,
                                                                                     getSuggestionCompletions() );
        popup.show();
    }

    /**
     * Builds all the condition widgets.
     */
    private void renderLhs( final RuleModel model ) {

        for ( int i = 0; i < model.lhs.length; i++ ) {
            DirtyableVerticalPane vert = new DirtyableVerticalPane();
            vert.setWidth( "100%" );

            //if lockLHS() set the widget RO, otherwise let them decide.
            Boolean readOnly = this.lockLHS() ? true : null;

            IPattern pattern = model.lhs[ i ];

            RuleModellerWidget w = getWidgetFactory().getWidget( this,
                                                                 eventBus,
                                                                 pattern,
                                                                 readOnly );
            w.addOnModifiedCommand( this.onWidgetModifiedCommand );

            vert.add( wrapLHSWidget( model,
                                     i,
                                     w ) );
            vert.add( spacerWidget() );

            layout.setWidget( currentLayoutRow,
                              0,
                              new DirtyableHorizontalPane() );
            layout.setWidget( currentLayoutRow,
                              1,
                              new DirtyableHorizontalPane() );

            layout.setWidget( currentLayoutRow,
                              2,
                              this.wrapLineNumber( i + 1,
                                                   true ) );
            layout.getFlexCellFormatter().setHorizontalAlignment( currentLayoutRow,
                                                                  2,
                                                                  HasHorizontalAlignment.ALIGN_CENTER );
            layout.getFlexCellFormatter().setVerticalAlignment( currentLayoutRow,
                                                                2,
                                                                HasVerticalAlignment.ALIGN_MIDDLE );

            layout.setWidget( currentLayoutRow,
                              3,
                              vert );
            layout.getFlexCellFormatter().setHorizontalAlignment( currentLayoutRow,
                                                                  3,
                                                                  HasHorizontalAlignment.ALIGN_LEFT );
            layout.getFlexCellFormatter().setVerticalAlignment( currentLayoutRow,
                                                                3,
                                                                HasVerticalAlignment.ALIGN_TOP );
            layout.getFlexCellFormatter().setWidth( currentLayoutRow,
                                                    3,
                                                    "100%" );

            if ( !w.isFactTypeKnown() ) {
                final Image image = GuidedRuleEditorImages508.INSTANCE.Error();
                image.setTitle( Constants.INSTANCE.InvalidPatternSectionDisabled() );
                this.addLineIcon( currentLayoutRow,
                                  0,
                                  image );
            }

            final int index = i;
            if ( !( this.lockLHS() || w.isReadOnly() ) ) {
                this.addActionsButtonsToLayout( Constants.INSTANCE.AddAConditionBelow(),
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        showConditionSelector( index + 1 );
                                                    }
                                                },
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        model.moveLhsItemDown( index );
                                                        refreshWidget();
                                                    }
                                                },
                                                new ClickHandler() {

                                                    public void onClick( ClickEvent event ) {
                                                        model.moveLhsItemUp( index );
                                                        refreshWidget();
                                                    }
                                                }
                                              );
            }

            this.lhsWidgets.add( w );
            currentLayoutRow++;
        }

    }

    private HTML spacerWidget() {
        HTML h = new HTML( "&nbsp;" ); //NON-NLS
        h.setHeight( "2px" ); //NON-NLS
        return h;
    }

    private Widget wrapLineNumber( int number,
                                   boolean isLHSLine ) {
        String id = "rhsLine";
        if ( isLHSLine ) {
            id = "lhsLine";
        }
        id += number;
        DirtyableHorizontalPane horiz = new DirtyableHorizontalPane();
        horiz.add( new HTML( "<div class='form-field' id='" + id + "'>" + number + ".</div>" ) );
        return horiz;
    }

    /**
     * This adds the widget to the UI, also adding the remove icon.
     */
    private Widget wrapLHSWidget( final RuleModel model,
                                  int i,
                                  RuleModellerWidget w ) {
        final DirtyableFlexTable wrapper = new DirtyableFlexTable();
        final Image remove = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall();
        remove.setTitle( Constants.INSTANCE.RemoveThisENTIREConditionAndAllTheFieldConstraintsThatBelongToIt() );
        final int idx = i;
        remove.addClickHandler( new ClickHandler() {

            public void onClick( ClickEvent event ) {
                if ( Window.confirm( Constants.INSTANCE.RemoveThisEntireConditionQ() ) ) {
                    if ( model.removeLhsItem( idx ) ) {
                        refreshWidget();

                        //Signal possible change in Template variables
                        TemplateVariablesChangedEvent tvce = new TemplateVariablesChangedEvent( model );
                        eventBus.fireEventFromSource( tvce,
                                                      model );
                    } else {
                        ErrorPopup.showMessage( Constants.INSTANCE.CanTRemoveThatItemAsItIsUsedInTheActionPartOfTheRule() );
                    }
                }
            }
        } );

        wrapper.getColumnFormatter().setWidth( 0,
                                               "100%" );
        w.setWidth( "100%" );
        wrapper.setWidget( 0,
                           0,
                           w );
        if ( !( this.lockLHS() || w.isReadOnly() ) || !w.isFactTypeKnown() ) {
            wrapper.setWidget( 0,
                               1,
                               remove );
            wrapper.getColumnFormatter().setWidth( 1,
                                                   "20px" );
        }

        return wrapper;
    }

    /**
     * This adds the widget to the UI, also adding the remove icon.
     */
    private Widget wrapRHSWidget( final RuleModel model,
                                  int i,
                                  RuleModellerWidget w ) {
        final DirtyableFlexTable wrapper = new DirtyableFlexTable();
        final Image remove = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall();
        remove.setTitle( Constants.INSTANCE.RemoveThisAction() );
        final int idx = i;
        remove.addClickHandler( new ClickHandler() {

            public void onClick( ClickEvent event ) {
                if ( Window.confirm( Constants.INSTANCE.RemoveThisItem() ) ) {
                    model.removeRhsItem( idx );
                    refreshWidget();

                    //Signal possible change in Template variables
                    TemplateVariablesChangedEvent tvce = new TemplateVariablesChangedEvent( model );
                    eventBus.fireEventFromSource( tvce,
                                                  model );
                }
            }
        } );

        //        if ( !(w instanceof ActionRetractFactWidget) ) {
        //            w.setWidth( "100%" );
        //            horiz.setWidth( "100%" );
        //        }

        wrapper.getColumnFormatter().setWidth( 0,
                                               "100%" );
        w.setWidth( "100%" );
        wrapper.setWidget( 0,
                           0,
                           w );

        if ( !( this.lockRHS() || w.isReadOnly() ) || !w.isFactTypeKnown() ) {
            wrapper.setWidget( 0,
                               1,
                               remove );
            wrapper.getColumnFormatter().setWidth( 1,
                                                   "20px" );
        }

        return wrapper;
    }

    private void addLineIcon( int row,
                              int col,
                              Image icon ) {
        Widget widget = layout.getWidget( row,
                                          col );
        if ( widget instanceof DirtyableHorizontalPane ) {
            DirtyableHorizontalPane horiz = (DirtyableHorizontalPane) widget;
            horiz.add( icon );
        }
    }

    private void clearLineIcons( int row,
                                 int col ) {
        if ( layout.getCellCount( row ) <= col ) {
            return;
        }
        Widget widget = layout.getWidget( row,
                                          col );
        if ( widget instanceof DirtyableHorizontalPane ) {
            DirtyableHorizontalPane horiz = (DirtyableHorizontalPane) widget;
            horiz.clear();
        }
    }

    private void clearLinesIcons( int col ) {
        for ( int i = 0; i < layout.getRowCount(); i++ ) {
            this.clearLineIcons( i,
                                 col );
        }
    }

    private void addActionsButtonsToLayout( String title,
                                            ClickHandler addBelowListener,
                                            ClickHandler moveDownListener,
                                            ClickHandler moveUpListener ) {

        final DirtyableHorizontalPane hp = new DirtyableHorizontalPane();

        Image addPattern = CommonAltedImages.INSTANCE.NewItemBelow();
        addPattern.setTitle( title );
        addPattern.addClickHandler( addBelowListener );

        Image moveDown = CommonAltedImages.INSTANCE.MoveDown();
        moveDown.setTitle( Constants.INSTANCE.MoveDown() );
        moveDown.addClickHandler( moveDownListener );

        Image moveUp = CommonAltedImages.INSTANCE.MoveUp();
        moveUp.setTitle( Constants.INSTANCE.MoveUp() );
        moveUp.addClickHandler( moveUpListener );

        hp.add( addPattern );
        hp.add( moveDown );
        hp.add( moveUp );

        layout.setWidget( currentLayoutRow,
                          4,
                          hp );
        layout.getFlexCellFormatter().setHorizontalAlignment( currentLayoutRow,
                                                              4,
                                                              HasHorizontalAlignment.ALIGN_CENTER );
        layout.getFlexCellFormatter().setVerticalAlignment( currentLayoutRow,
                                                            4,
                                                            HasVerticalAlignment.ALIGN_MIDDLE );
    }

    public RuleModel getModel() {
        return model;
    }

    /**
     * Returns true is a var name has already been used either by the rule, or
     * as a global.
     */
    public boolean isVariableNameUsed( String name ) {
        return model.isVariableNameUsed( name ) || getSuggestionCompletions().isGlobalVariable( name );
    }

    @Override
    public boolean isDirty() {
        return ( layout.hasDirty() || dirtyflag );
    }

    public PackageDataModelOracle getSuggestionCompletions() {
        return dataModel;
    }

    public ModellerWidgetFactory getWidgetFactory() {
        return widgetFactory;
    }

    public RuleModeller getRuleModeller() {
        return this;
    }

    public boolean isTemplate() {
        return widgetFactory.isTemplate();
    }

    public Path getPath() {
        return path;
    }

    public boolean isReadOnly() {
        return isReadOnly;
    }

    public boolean isDSLEnabled() {
        return isDSLEnabled;
    }

}
TOP

Related Classes of org.drools.workbench.screens.guided.rule.client.editor.RuleModeller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.