/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * 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 should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.tools.config.gui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.Box; import javax.swing.DefaultListModel; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceActionAdapter; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.dialogs.ButtonDialog; import com.rapidminer.repository.RepositoryException; import com.rapidminer.tools.I18N; import com.rapidminer.tools.PasswordInputCanceledException; import com.rapidminer.tools.config.Configurable; import com.rapidminer.tools.config.ConfigurationManager; /** * This dialog can be used to modify the user access rights of a {@link Configurable}s, which has a * remote source. The dialog shows two lists. One with users that have no access to a remote * {@link Configurable} and one list with users that have access. * * A user is able to select one or multiple user groups and put it to the other list. * * @author Sabrina Kirstein * */ public class ConfigurableUserAccessDialog extends ButtonDialog { private static final long serialVersionUID = 4537846891423068444L; private static final Icon LEFT_ICON = SwingTools.createIcon("24/nav_left.png"); private static final Icon RIGHT_ICON = SwingTools.createIcon("24/nav_right.png"); private Configurable configurable; private DefaultListModel<String> restrictedListModel; private DefaultListModel<String> accessListModel; private JList<String> restrictedList; private JList<String> accessList; private Set<String> originalAccessList; private boolean confirmed = false; public ConfigurableUserAccessDialog(Window owner, Configurable configurable) { super(owner, "configurable_user_access_dialog", ModalityType.MODELESS); this.configurable = configurable; initGui(); } private void initGui() { setModal(true); final JPanel selectionPanel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); restrictedListModel = new DefaultListModel<>(); restrictedList = new JList<>(restrictedListModel); restrictedList.setLayoutOrientation(JList.VERTICAL); restrictedList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); if (e.getClickCount() == 2) { allowAccessToSelectedUserGroups(); restrictedList.setSelectedIndex(-1); selectionPanel.requestFocus(); restrictedList.updateUI(); } } }); accessListModel = new DefaultListModel<>(); accessList = new JList<>(accessListModel); accessList.setLayoutOrientation(JList.VERTICAL); accessList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); if (e.getClickCount() == 2) { restrictAccessToSelectedUserGroups(); accessList.setSelectedIndex(-1); selectionPanel.requestFocus(); accessList.updateUI(); } } }); originalAccessList = new HashSet<>(); ProgressThread pt = new ProgressThread("load_user_groups") { @Override public void run() { List<String> allGroups; try { allGroups = configurable.getSource().getContentManager().getAllGroupNames(); } catch (PasswordInputCanceledException | RepositoryException e) { allGroups = new ArrayList<>( ConfigurationManager.getInstance().getPermittedGroupsForConfigurable(configurable)); } final Set<String> permittedGroups = ConfigurationManager.getInstance() .getPermittedGroupsForConfigurable(configurable); final List<String> allGroupsFinal = allGroups; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { for (String element : allGroupsFinal) { if (permittedGroups.contains(element)) { accessListModel.addElement(element); originalAccessList.add(element.toString()); } else { restrictedListModel.addElement(element); } } } }); } }; pt.start(); JPanel accessSelectionButtonsPanel = new JPanel(new BorderLayout()); JButton accessButton = null; if (RIGHT_ICON != null) { accessButton = new JButton(RIGHT_ICON); } else { accessButton = new JButton(">"); } accessButton.setToolTipText(I18N.getGUILabel("configurable_user_access_dialog.allow.label")); accessButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { allowAccessToSelectedUserGroups(); } }); JButton restrictButton = null; if (LEFT_ICON != null) { restrictButton = new JButton(LEFT_ICON); } else { restrictButton = new JButton("<"); } restrictButton.setToolTipText(I18N.getGUILabel("configurable_user_access_dialog.restrict.label")); restrictButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { restrictAccessToSelectedUserGroups(); } }); accessSelectionButtonsPanel.add(accessButton, BorderLayout.NORTH); accessSelectionButtonsPanel.add(restrictButton, BorderLayout.SOUTH); JScrollPane restrictedAccessScrollPane = new ExtendedJScrollPane(restrictedList) { private static final long serialVersionUID = 8474453689364798720L; @Override public Dimension getPreferredSize() { return new Dimension((int) (getWidth() * 0.25d), super.getPreferredSize().height); } }; JScrollPane allowedAccessScrollPane = new ExtendedJScrollPane(accessList) { private static final long serialVersionUID = -7089596032717082128L; @Override public Dimension getPreferredSize() { return new Dimension((int) (getWidth() * 0.25d), super.getPreferredSize().height); } }; c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.BOTH; restrictedAccessScrollPane.setBorder(createTitledBorder("Restricted")); selectionPanel.add(restrictedAccessScrollPane, c); c.gridx = 1; c.gridy = 0; c.weightx = 0; c.weighty = 1; c.fill = GridBagConstraints.NONE; selectionPanel.add(accessSelectionButtonsPanel, c); c.gridx = 2; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.BOTH; allowedAccessScrollPane.setBorder(createTitledBorder("Access")); selectionPanel.add(allowedAccessScrollPane, c); layoutDefault(selectionPanel, createButtons(), NORMAL); } /** * Creates and returns the button component. * * @return */ private JPanel createButtons() { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new GridBagLayout()); GridBagConstraints buttonGBC = new GridBagConstraints(); buttonGBC.gridx = 0; buttonGBC.weightx = 1.0; buttonGBC.fill = GridBagConstraints.HORIZONTAL; buttonGBC.insets = new Insets(5, 5, 5, 5); buttonPanel.add(Box.createHorizontalGlue(), buttonGBC); JButton saveButton = new JButton(new ResourceActionAdapter(false, "configurable_user_access_dialog.save") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { confirmed = true; dispose(); } }); buttonGBC.gridx += 1; buttonGBC.weightx = 0.0; buttonPanel.add(saveButton, buttonGBC); ResourceAction cancelAction = new ResourceAction(false, "cancel") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { dispose(); } }; JButton removeButton = new JButton(cancelAction); getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "CANCEL"); getRootPane().getActionMap().put("CANCEL", cancelAction); buttonGBC.gridx += 1; buttonPanel.add(removeButton, buttonGBC); return buttonPanel; } private void allowAccessToSelectedUserGroups() { List<String> userKeys = restrictedList.getSelectedValuesList(); int[] newSelection = new int[userKeys.size()]; for (int i = 0; i < userKeys.size(); i++) { String userKey = userKeys.get(i); restrictedListModel.removeElement(userKey); int index = addElement(accessListModel, userKey); if (index != -1) { newSelection[i] = index; } } restrictedList.setSelectedIndex(-1); accessList.setSelectedIndices(newSelection); accessList.updateUI(); } private void restrictAccessToSelectedUserGroups() { List<String> userKeys = accessList.getSelectedValuesList(); int[] newSelection = new int[userKeys.size()]; for (int i = 0; i < userKeys.size(); i++) { String userKey = userKeys.get(i); accessListModel.removeElement(userKey); int index = addElement(restrictedListModel, userKey); if (index != -1) { newSelection[i] = index; } } accessList.setSelectedIndex(-1); restrictedList.setSelectedIndices(newSelection); restrictedList.updateUI(); } /** * Adds the element sorted to the model * * @param model * @param element * @return index of the new element */ private int addElement(DefaultListModel<String> model, String element) { if (model.isEmpty()) { model.addElement(element); return 0; } else { for (int j = 0; j < model.getSize(); j++) { int compareValue = String.CASE_INSENSITIVE_ORDER.compare(model.getElementAt(j).toString(), element); if (compareValue > 0) { model.add(j, element); return j; } if (j == model.getSize() - 1) { model.add(j + 1, element); return j + 1; } } } // sth went wrong return -1; } /** * * @return the selected user groups that have access to the configurable */ public Set<String> getPermittedUserGroups() { Set<String> permittedUserGroups = new HashSet<>(); if (confirmed) { for (int i = 0; i < accessListModel.getSize(); i++) { permittedUserGroups.add(accessListModel.getElementAt(i).toString()); } return permittedUserGroups; } else { return originalAccessList; } } }