GroupsView.java

/*
** Module   : GroupsView.java
** Abstract : GroupsView provides a view to manage groups.
**
** Copyright (c) 2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- ----------------Description----------------------
** 001 SBI 20170601 Created initial version.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.admin.client.application.home.accounts.groups;


import java.util.*;

import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.TextBox;
import org.gwtbootstrap3.client.ui.gwt.DataGrid;

import com.goldencode.p2j.admin.TaggedName;
import com.goldencode.p2j.admin.client.NameTokens;
import com.goldencode.p2j.admin.client.application.home.BaseViewWithUiHandlers;
import com.goldencode.p2j.admin.client.widget.*;
import com.goldencode.p2j.admin.shared.*;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.inject.Inject;

/**
 * GroupsView provides a view to manage groups.
 */
public class GroupsView
extends BaseViewWithUiHandlers<GroupsUIHandlers>
implements GroupsPresenter.MyView
{
   /**
    * GWT UI creator
    */
   interface Binder
   extends UiBinder<Widget, GroupsView>
   {}
   
   /** The Refresh button */
   @UiField
   Button refresh;

   /** The Add group button */
   @UiField
   Button addGroup;

   /** The Delete group button */
   @UiField
   Button deleteGroup;

   /** The clone group button */
   @UiField
   Button cloneGroup;

   /** The edit group button */
   @UiField
   Button editGroup;

   /** The Switch to ACLs button */
   @UiField
   Button switchToACLs;

   /** The Delete user button */
   @UiField
   Button deleteUser;
   
   /** The Add user button */
   @UiField
   Button addUser;
   
   /** The text box representing the new user account name */
   @UiField
   TextBox newUser;

   /** The Populate users button */
   @UiField
   Button populateUsers;
   
   /** The Add Selected button */
   @UiField
   Button addSelected;
   
   /** The filter text box selector */
   @UiField
   TextBox filterSelector;
   
   /** The Filter button */
   @UiField
   Button filterUsers;
   
   /** The all groups table view */
   @UiField(provided = true)
   DataGrid<TaggedName> groupsGrid = GridHelper.create();
   
   /** The group users table view (all users in the given group) */
   @UiField(provided = true)
   DataGrid<TaggedName> groupUsersGrid = GridHelper.create();
   
   /** The all users table view */
   @UiField(provided = true)
   DataGrid<TaggedName> allUsersGrid = GridHelper.create();
   
   /** modal container */
   @UiField
   Widget modalFragment;

   /** Column names for all groups table. */
   private final String[] groupsColumnNames = { "Group ID", "Description" };
   
   /** Column names for all users table and group users table. */
   private final String[] groupUsersColumnNames = { "User ID", "Person" };
   
   /** The all groups data provider */
   private final ListDataProvider<TaggedName> groupsProvider;
   
   /** The all groups selection model */
   private final MultiSelectionModel<TaggedName> groupsSelectionModel;
   
   /** The all groups grid handle */
   private final GridHandle<TaggedName> groupsGridHandle;
   
   /** The group users data provider */
   private final ListDataProvider<TaggedName> groupUsersProvider;
   
   /** The group users selection model */
   private final MultiSelectionModel<TaggedName> groupUsersSelectionModel;
   
   /** The group users grid handle */
   private final GridHandle<TaggedName> groupUsersGridHandle;
   
   /** The all users data provider */
   private final ListDataProvider<TaggedName> allUsersProvider;
   
   /** The all users selection model */
   private final MultiSelectionModel<TaggedName> allUsersSelectionModel;
   
   /** The all users grid handle */
   private final GridHandle<TaggedName> allUsersGridHandle;

   /** The Group Definition View */
   private final GroupDefinitionView groupDefinitionView;
   
   /** The Deleting Groups Alert view */
   private final DeletingGroupsAlert deletingGroupsAlert;
   
   /** The Clone Group View */
   private final CloneGroupView cloneGroupView;
   
   /** The Unassigning Users Alert view */
   private final UnassigningUsersAlert unassigningUsersAlert;
   
   /**
    * Constructs this view used by by MPV gwtplatform of ArcBees Inc.
    * 
    * @param    binder
    *           The injected GWT UI Binder
    * @param    groupDefinitionView
    *           The injected Group Definition View
    * @param    deletingGroupsAlert
    *           The injected Deleting Groups Alert view
    * @param    cloneGroupView
    *           The injected Clone Group View
    * @param    unassigningUsersAlert
    *           The injected Unassigning Users Alert view
    */
   @Inject
   public GroupsView(Binder binder,
                     GroupDefinitionView groupDefinitionView,
                     DeletingGroupsAlert deletingGroupsAlert,
                     CloneGroupView cloneGroupView,
                     UnassigningUsersAlert unassigningUsersAlert)
   {
      initWidget(binder.createAndBindUi(this));
      
      
      
      this.groupDefinitionView = groupDefinitionView;
      this.deletingGroupsAlert = deletingGroupsAlert;
      this.cloneGroupView = cloneGroupView;
      this.unassigningUsersAlert = unassigningUsersAlert;
   
      this.groupsGridHandle = initTable(groupsGrid, groupsColumnNames, true, true);
      this.groupsProvider = groupsGridHandle.getDataProvider();
      this.groupsSelectionModel = (MultiSelectionModel<TaggedName>) groupsGridHandle.getSelectionModel();
      this.groupsSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
      {
         @Override
         public void onSelectionChange(SelectionChangeEvent event)
         {
            Set<TaggedName> selected = GroupsView.this.groupsSelectionModel.getSelectedSet();
            if (selected.size() != 1)
            {
               GroupsView.this.allUsersSelectionModel.clear();
            }
            GroupsView.this.getUiHandlers().onGroupSelected(selected);
         }
      });
      
      this.groupUsersGridHandle = initTable(groupUsersGrid, groupUsersColumnNames, true, true);
      
      this.groupUsersSelectionModel = (MultiSelectionModel<TaggedName>) this.groupUsersGridHandle.getSelectionModel();
      this.groupUsersProvider = this.groupUsersGridHandle.getDataProvider();
      this.groupUsersSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
      {
         @Override
         public void onSelectionChange(SelectionChangeEvent event)
         {
            Set<TaggedName> selected = GroupsView.this.groupUsersSelectionModel.getSelectedSet();
            GroupsView.this.getUiHandlers().onUserSelected(selected);
         }
      });
      
      this.allUsersGridHandle = initTable(allUsersGrid, groupUsersColumnNames, true, true);
      this.allUsersProvider = this.allUsersGridHandle.getDataProvider();
      this.allUsersSelectionModel = (MultiSelectionModel<TaggedName>)this.allUsersGridHandle.getSelectionModel();
      this.allUsersSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
      {
         
         @Override
         public void onSelectionChange(SelectionChangeEvent event)
         {
            if (GroupsView.this.groupsSelectionModel.getSelectedSet().size() == 1)
            {
               Set<TaggedName> selected = GroupsView.this.allUsersSelectionModel.getSelectedSet();
               List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
               usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));

               GroupsView.this.addSelected.setEnabled(!usersInGroup.containsAll(selected));
            }
            else
            {
               GroupsView.this.allUsersSelectionModel.clear();
            }
         }
      });
      
      ((com.google.gwt.user.cellview.client.DataGrid<TaggedName>) groupsGrid).setMinimumTableWidth(300, Unit.PX);
      setupModalSlot(GroupsPresenter.MODAL_CONTENT, modalFragment);
      addDialog(groupDefinitionView);
      addDialog(deletingGroupsAlert);
      addDialog(cloneGroupView);
      addDialog(unassigningUsersAlert);
   }
   
   /**
    * Setups the given table view.
    * 
    * @param    grid
    *           The given table view
    * @param    columnNames
    *           The given column names
    * @param    multiSelection
    *           The flag defines if the table view supports multiple rows or single row selections
    * @param    sortable
    *           The flag defines if the table columns can change its rows sort order or not.
    * 
    * @return   The grid handle
    */
   private GridHandle<TaggedName> initTable(DataGrid<TaggedName> grid, String[] columnNames,
            boolean multiSelection, boolean sortable)
   {
      GridHelper.ColumnInfo<TaggedName> col1 = new GridHelper.ColumnInfo<TaggedName>(
               columnNames[0],
               (tn) -> tn.getName(),
               (sortable) ? (tn1, tn2) -> tn1.getName().compareTo(tn2.getName()) : null
               );
      GridHelper.ColumnInfo<TaggedName> col2 = new GridHelper.ColumnInfo<TaggedName>(
               columnNames[1],
               (tn) -> tn.getTag(),
               (sortable) ? (tn1, tn2) -> tn1.getTag().compareTo(tn2.getTag()) : null
               );
      
      return GridHelper.initListGrid(grid, multiSelection, sortable, col1, col2);
   }

   /**
    * Updates the table view data provider with new data.
    * 
    * @param    grid
    *           The table view
    * @param    dataProvider
    *           The data provider
    * @param    records
    *           The new data
    */
   private void updateDataProvider(DataGrid<TaggedName> grid,
                                   ListDataProvider<TaggedName> dataProvider,
                                   TaggedName[] records)
   {
      GridHelper.updateDataProvider(grid, dataProvider, records);
   }
   
   /**
    * Updates the table view data provider with new data.
    * 
    * @param    dataGrid
    *           The table view
    * @param    dataProvider
    *           The data provider
    * @param    records
    *           The new data
    * @param    filterExp
    *           The regular expression that is used to select rows that satisfy the given criteria
    */
   private void updateDataProvider(DataGrid<TaggedName> dataGrid,
                                   ListDataProvider<TaggedName> dataProvider,
                                   TaggedName[] records,
                                   RegExp filterExp)
   {
      dataProvider.getList().clear();
      
      if (records == null)
      {
         return;
      }
      
      GridHelper.updateDataProvider(dataGrid, dataProvider, records, filterExp);
   }

   /**
    * Sets the all groups table model.
    * 
    * @param    groups
    *           The array of groups given by tagged names
    */
   @Override
   public void setGroups(TaggedName[] groups)
   {
      logger.info("setGroups " + groups);
      groupsSelectionModel.clear();
      updateDataProvider(groupsGrid, groupsProvider, groups);
   }

   /**
    * The Refresh button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("refresh")
   void onRefresh(ClickEvent e)
   {
      getUiHandlers().onRefresh();
   }
   
   /**
    * The Add Group button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("addGroup")
   void onAddGroup(ClickEvent e)
   {
      logger.info("onAddGroup");
      getUiHandlers().setupAddGroupDialog();
   }
   
   /**
    * The Clone Group button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("cloneGroup")
   void onCloneGroup(ClickEvent e)
   {
      TaggedName[] groups = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      getUiHandlers().setupCloneGroupDialog(groups[0]);
   }
   
   /**
    * The Edit Group button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("editGroup")
   void onEditGroup(ClickEvent e)
   {
      logger.info("onEditGroup");
      TaggedName[] groups = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      getUiHandlers().setupEditGroupDialog(groups[0]);
   }
   
   /**
    * The Populate button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("populateUsers")
   void onPopulateUsers(ClickEvent e)
   {
      getUiHandlers().populateAndRefreshAllUsers();
   }
   
   /**
    * The Delete Group button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("deleteGroup")
   void onDeleteGroup(ClickEvent e)
   {
      logger.info("onDeleteGroup");
      TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      
      getUiHandlers().setupDeletingGroupsAlert(groups);
   }

   /**
    * The Delete User button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("deleteUser")
   void onDeleteUser(ClickEvent e)
   {
      logger.info("onDeleteUser");

      TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      TaggedName[] users = this.groupUsersSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      
      getUiHandlers().setupUnassigningUsersAlert(groups[0], users);
   }
   
   /**
    * The Add User button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("addUser")
   void onAddUser(ClickEvent e)
   {
      logger.info("onAddUser");

      TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      //TODO validation
      
      getUiHandlers().addUserToGroup(groups[0], newUser.getText());
   }
   
   /**
    * The Filter Users button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("filterUsers")
   void onFilterUsers(ClickEvent e)
   {
      logger.info("onFilterUsers");
      getUiHandlers().setUsersFilter(filterSelector.getText());
   }
   
   /**
    * The Add Selected button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("addSelected")
   void onAddSelected(ClickEvent e)
   {
      logger.info("AddSelected");
      List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
      Set<TaggedName> selected = this.allUsersSelectionModel.getSelectedSet();
      selected.removeAll(usersInGroup);
      TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
      getUiHandlers().addUsersToGroup(groups[0], selected);
   }
   
   /**
    * Sets the group users table model.
    * 
    * @param    users
    *           The array of group users given by tagged names
    */
   @Override
   public void setUsersInGroup(TaggedName[] users)
   {
      this.groupUsersSelectionModel.clear();
      this.allUsersSelectionModel.clear();
      updateDataProvider(groupUsersGrid, groupUsersProvider, users);
      
      List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
      usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));
      
      GroupsView.this.addSelected.setEnabled(false);
   }

   /**
    * Sets all users model.
    * 
    * @param    allUsers
    *           The array of all users accounts given by tagged names
    * @param    filterExp
    *           The search template to filter the displayed users
    */
   @Override
   public void setAllUsers(TaggedName[] allUsers, RegExp filterExp)
   {
      updateDataProvider(allUsersGrid, allUsersProvider,
               allUsers, filterExp);
      if (GroupsView.this.groupsSelectionModel.getSelectedSet().size() == 1)
      {
         List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
         usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));
      }
      else
      {
         GroupsView.this.allUsersSelectionModel.clear();
      }
   }

   /**
    * Gets a reference to the Group Definition View.
    * 
    * @return   The Group Definition View
    */
   @Override
   public GroupDefinitionView getGroupDefinitionView()
   {
      return groupDefinitionView;
   }

   /**
    * Gets a reference to the Deleting Groups Alert View.
    * 
    * @return   The Deleting Groups Alert View
    */
   @Override
   public DeletingGroupsAlert getDeletingGroupsAlert()
   {
      return deletingGroupsAlert;
   }

   /**
    * Gets a reference to the Clone Group View.
    * 
    * @return   The Clone Group View
    */
   @Override
   public CloneGroupView getCloneGroupView()
   {
      return cloneGroupView;
   }

   /**
    * Provides all components that must be managed by its view state machine.
    * 
    * @return   The array of components managed by its view state machine
    */
   @Override
   public HasEnabled[] get()
   {
      return new HasEnabled[] {
               refresh,
               addGroup,
               deleteGroup,
               cloneGroup,
               editGroup,
               switchToACLs,
               
               newUser,
               addUser,
               deleteUser,
               
               populateUsers,
               addSelected,
               filterSelector,
               filterUsers
      };
   }

   /**
    * Gets a reference to the Unassigning Users Alert View.
    * 
    * @return   The Unassigning Users Alert View
    */
   @Override
   public UnassigningUsersAlert getUnassigningUsersAlert()
   {
      return unassigningUsersAlert;
   }

   /**
    * Tests if this group has been selected.
    * 
    * @param    group
    *           The target group
    * 
    * @return   True iff the target group has een selected, otherwise false.
    */
   @Override
   public boolean isSelectedGroup(TaggedName group)
   {
      return groupsSelectionModel.isSelected(group);
   }

   /**
    * Tests if these users have been selected.
    * 
    * @param    users
    *           The array of selected user accounts given by tagged names
    * 
    * @return   True if all tested users have been selected, otherwise false.
    */
   @Override
   public boolean isSelectedUsers(TaggedName[] users)
   {
      return groupUsersSelectionModel.getSelectedSet().containsAll(Arrays.asList(users));
   }
   
   /**
    * Changes the Populate button's label from "Populate" to "Refresh"
    * 
    * @param    populated
    *           The flag which true value means to change the Populate label to Refresh one
    */
   @Override
   public void togglePopulateUsersButton(boolean populated)
   {
      if (populated)
      {
         populateUsers.setText("Refresh");
      }
   }

   /**
    * The Switch To ACLs button click handler.
    * 
    * @param    e
    *           Click event
    */
   @UiHandler("switchToACLs")
   void onSwitchToACLs(ClickEvent e)
   {
      logger.info("onSwitchToACLs");
      TaggedName selected = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(
               new TaggedName[0])[0];
      getUiHandlers().switchToACLs(selected);
   }

   /**
    * Returns pairs of a report parameter key and its value
    * 
    * @return   The enumeration map of report parameters keys to their values
    */
   @Override
   public EnumMap<ReportParameters, Object> getReportParameters()
   {
      EnumMap<ReportParameters, Object> parameters = new EnumMap<ReportParameters, Object>(
               ReportParameters.class);
      parameters.put(ReportParameters.SELECTION, groupsSelectionModel.getSelectedSet().toArray(
               new TaggedName[groupsSelectionModel.getSelectedSet().size()]));
      parameters.put(ReportParameters.TITLE, "Groups");
      parameters.put(ReportParameters.REPORT_ID, Reports.GROUPS);
      parameters.put(ReportParameters.PAPER_FORMAT, PaperFormat.A4);
      parameters.put(ReportParameters.PAPER_ORIENT, PaperOrientation.PORTRAIT);
      
      return parameters;
   }

   /**
    * Returns the size of all data to preview or the size of selected data to preview
    * 
    * @param    range
    *           The target range of selected data to preview
    * @return   The size of the selected data
    */
   @Override
   public int getDataSize(Range range)
   {
      if (range == Range.SELECTION)
      {
         return groupsSelectionModel.getSelectedSet().size();
      }
      
      return groupsProvider.getList().size();
   }

   /**
    * Returns the value of the preview dialog parameter.
    * 
    * @param    parameter
    *           The preview dialog parameter key
    * 
    * @return   The value of the preview dialog parameter
    */
   @Override
   public String getPreviewDialogParameter(PreviewDialogParameters parameter)
   {
      int selectedRecordsNumber = groupsSelectionModel.getSelectedSet().size();
      int allRecordsNumber = groupsProvider.getList().size();
      switch (parameter)
      {
         case HELP_TEXT:
            String hlpText;
            if (selectedRecordsNumber > 0)
            {
               hlpText = "<h4>Please refine your request.</h4>";
            }
            else
            {
               if (allRecordsNumber > 1)
               {
                  hlpText = "<h4>" + allRecordsNumber + " group accounts being printed. Continue?</h4>";
               }
               else if (allRecordsNumber == 1)
               {
                  hlpText = "<h4>1 group account being printed. Continue?</h4>";
               }
               else
               {
                  hlpText = "<h4>There are no groups to print. Continue?</h4>";
               }
            }
            
            return hlpText;
         case TITLE:
            return "Printing Groups";
         case RANGE_ALL_LABEL:
            if (allRecordsNumber > 2)
            {
               return "all " + allRecordsNumber + " group accounts";
            }
            else if (allRecordsNumber == 2)
            {
               return "both group accounts";
            }
            
            break;
         case RANGE_SELECTION_LABEL:
            if (selectedRecordsNumber > 1)
            {
               return selectedRecordsNumber + " selected group accounts";
            }
            else if (selectedRecordsNumber == 1)
            {
               return "the selected group account";
            }
            
            break;
      }
      
      return null;
   }

   /**
    * Returns url path to this view.
    * 
    * @return   The url path.
    */
   @Override
   public String getPathToPrintPreviewOwner()
   {
      return NameTokens.GROUPS;
   }

   /**
    * Select a group by its name.
    * 
    * @param    groupName
    *           The group name
    */
   @Override
   public void selectGroupByName(String groupName)
   {
      groupsSelectionModel.clear();
      groupsProvider.getList().forEach(group -> {
         if (group.getName().equals(groupName))
         {
            Scheduler.get().scheduleDeferred(new ScheduledCommand()
            {
               @Override
               public void execute()
               {
                  groupsSelectionModel.setSelected(group, true);
               }
            });
         }
      });
   }
}