Coverage Report - org.openpermis.editor.policy.view.RoleHierarchyEditor
 
Classes in this File Line Coverage Branch Coverage Complexity
RoleBrowser
0%
0/26
N/A
2.043
RoleBrowser$1
0%
0/4
0%
0/4
2.043
RoleBrowser$2
0%
0/4
0%
0/4
2.043
RoleBrowser$ChildrenTableModel
0%
0/10
0%
0/4
2.043
RoleBrowser$NoHeaderJTable
0%
0/15
0%
0/12
2.043
RoleBrowser$ParentsTableModel
0%
0/6
N/A
2.043
RoleHierarchyEditor
0%
0/107
0%
0/50
2.043
RoleHierarchyEditor$1
0%
0/3
N/A
2.043
RoleHierarchyEditor$2
0%
0/8
0%
0/10
2.043
RoleNode
0%
0/29
0%
0/8
2.043
RoleNodeRenderer
0%
0/10
0%
0/2
2.043
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.editor.policy.view;
 11  
 
 12  
 import java.awt.Component;
 13  
 import java.awt.Container;
 14  
 import java.beans.PropertyChangeEvent;
 15  
 import java.beans.PropertyChangeListener;
 16  
 import java.util.ArrayList;
 17  
 import java.util.Arrays;
 18  
 import java.util.Collections;
 19  
 import java.util.Enumeration;
 20  
 import java.util.List;
 21  
 import java.util.Set;
 22  
 
 23  
 import javax.swing.JComponent;
 24  
 import javax.swing.JLabel;
 25  
 import javax.swing.JOptionPane;
 26  
 import javax.swing.JPanel;
 27  
 import javax.swing.JScrollPane;
 28  
 import javax.swing.JTable;
 29  
 import javax.swing.JTree;
 30  
 import javax.swing.JViewport;
 31  
 import javax.swing.ListSelectionModel;
 32  
 import javax.swing.UIManager;
 33  
 import javax.swing.border.Border;
 34  
 import javax.swing.event.AncestorEvent;
 35  
 import javax.swing.event.AncestorListener;
 36  
 import javax.swing.event.ListSelectionEvent;
 37  
 import javax.swing.event.ListSelectionListener;
 38  
 import javax.swing.event.TreeSelectionEvent;
 39  
 import javax.swing.event.TreeSelectionListener;
 40  
 import javax.swing.table.AbstractTableModel;
 41  
 import javax.swing.table.TableModel;
 42  
 import javax.swing.table.DefaultTableCellRenderer.UIResource;
 43  
 import javax.swing.tree.DefaultTreeModel;
 44  
 import javax.swing.tree.TreeCellRenderer;
 45  
 import javax.swing.tree.TreeNode;
 46  
 import javax.swing.tree.TreePath;
 47  
 import javax.swing.tree.TreeSelectionModel;
 48  
 
 49  
 import org.jdesktop.application.Action;
 50  
 import org.jdesktop.application.ApplicationContext;
 51  
 import org.jdesktop.beansbinding.BindingGroup;
 52  
 import org.slf4j.Logger;
 53  
 import org.slf4j.LoggerFactory;
 54  
 
 55  
 import com.jgoodies.forms.layout.CellConstraints;
 56  
 import com.jgoodies.forms.layout.FormLayout;
 57  
 
 58  
 import org.openpermis.editor.policy.adapter.AdapterTrader;
 59  
 import org.openpermis.editor.policy.presenter.RoleHierarchyPresenter;
 60  
 import org.openpermis.policy.Role;
 61  
 import org.openpermis.policy.bean.RoleHierarchyBean;
 62  
 
 63  
 /**
 64  
  * Editor for a {@link RoleHierarchyPresenter}.
 65  
  * @since 0.3.0
 66  
  */
 67  0
 public class RoleHierarchyEditor
 68  
         extends AbstractEditor<RoleHierarchyPresenter>
 69  
         implements AncestorListener
 70  
 {
 71  
 
 72  
         //---- Static
 73  
 
 74  
         /**
 75  
          * The logger object of this class.
 76  
          * @since 0.3.0
 77  
          */
 78  0
         private static final Logger LOGGER = LoggerFactory.getLogger(RoleHierarchyEditor.class);
 79  
 
 80  
         //---- Classes
 81  
 
 82  
         /**
 83  
          * @since 0.3.0
 84  
          */
 85  0
         private JTree tree = new JTree();
 86  
 
 87  
         /**
 88  
          * @since 0.3.0
 89  
          */
 90  0
         private RoleBrowser roleBrowser = new RoleBrowser(this);
 91  
 
 92  
         /**
 93  
          * @since 0.3.0
 94  
          */
 95  0
         private PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
 96  0
                 public void propertyChange (PropertyChangeEvent evt) {
 97  0
                         updateTree();
 98  0
                 }
 99  
         };
 100  
 
 101  
         //---- Constructors
 102  
 
 103  
         /**
 104  
          * Creates a {@link RoleHierarchyEditor}.
 105  
          * @since 0.3.0
 106  
          */
 107  
         public RoleHierarchyEditor (
 108  
                 ApplicationContext context, AdapterTrader trader, RoleHierarchyPresenter presenter
 109  
         ) {
 110  0
                 super(context, trader, presenter);
 111  0
         }
 112  
 
 113  
         //---- Methods
 114  
 
 115  
         /**
 116  
          * Given a parent role, include a role among its children.
 117  
          * @since 0.3.0
 118  
          */
 119  
         @Action
 120  
         public void includeRole () {
 121  0
                 LOGGER.debug("includeRole");
 122  
 
 123  0
                 List<String> roleNamesList = new ArrayList<String>();
 124  
 
 125  0
                 final String selectedRole = this.roleBrowser.getSelectedNode().getRole();
 126  0
                 final Set<String> roles = getPresenter().getRoleHierarchyBean().getRoles();
 127  
 
 128  0
                 for (String r : roles) {
 129  0
                         if (!getPresenter().getRoleHierarchyBean().isSubRole(selectedRole, r) &&
 130  
                                 !getPresenter().getRoleHierarchyBean().isSuperRole(selectedRole, r)) {
 131  0
                                 roleNamesList.add(r);
 132  
                         }
 133  
                 }
 134  
 
 135  0
                 String[] roleNamesArray = new String[roleNamesList.size()];
 136  
 
 137  0
                 roleNamesArray = roleNamesList.toArray(roleNamesArray);
 138  
 
 139  0
                 Arrays.sort(roleNamesArray);
 140  
 
 141  0
                 String s = (String) JOptionPane.showInputDialog(
 142  
                         null,
 143  
                         getResourceMap().getString("includeRole.Dialog.text"),
 144  
                         getResourceMap().getString("includeRole.Dialog.title"),
 145  
                         JOptionPane.PLAIN_MESSAGE,
 146  
                         null,
 147  
                         roleNamesArray,
 148  
                         ""
 149  
                 );
 150  
 
 151  0
                 if (s != null) {
 152  0
                         this.getPresenter().includeRole(this.roleBrowser.getSelectedNode().toString(), s);
 153  
                 }
 154  0
         }
 155  
 
 156  
         /**
 157  
          * Detaches a role from its parent.
 158  
          * @since 0.3.0
 159  
          */
 160  
         @Action
 161  
         public void detachRole () {
 162  0
                 LOGGER.debug("detachRole");
 163  
 
 164  0
                 final RoleNode selectedNode = this.roleBrowser.getSelectedNode();
 165  0
                 if (selectedNode == null) {
 166  0
                         return;
 167  
                 }
 168  
 
 169  0
                 int n = JOptionPane.showConfirmDialog(
 170  
                         null,
 171  
                         getResourceMap().getString("detachRole.Dialog.text"),
 172  
                         getResourceMap().getString("detachRole.Dialog.title"),
 173  
                         JOptionPane.YES_NO_OPTION
 174  
                 );
 175  
 
 176  0
                 if (n == 0) {
 177  0
                         this.getPresenter().detachRole(
 178  
                                 selectedNode.getParent().toString(),
 179  
                                 selectedNode.toString()
 180  
                         );
 181  
                 }
 182  0
         }
 183  
 
 184  
         /**
 185  
          * Adds a new role in the hierarchy.
 186  
          * @since 0.3.0
 187  
          */
 188  
         @Action
 189  
         public void addNewRole () {
 190  0
                 LOGGER.debug("addNewRole");
 191  
 
 192  0
                 String s = (String) JOptionPane.showInputDialog(
 193  
                         null,
 194  
                         getResourceMap().getString("addNewRole.Dialog.text"),
 195  
                         getResourceMap().getString("addNewRole.Dialog.title"),
 196  
                         JOptionPane.PLAIN_MESSAGE,
 197  
                         null,
 198  
                         null,
 199  
                         ""
 200  
                 );
 201  
 
 202  0
                 if (s != null) {
 203  0
                         this.getPresenter().addNewRole(s);
 204  
                 }
 205  0
         }
 206  
 
 207  
         /**
 208  
          * @since 0.3.0
 209  
          */
 210  
         private boolean checkReferences (String operation, String role) {
 211  0
                 final Role roleref = Role.create(getPresenter().getRoleHierarchyBean(), role);
 212  0
                 boolean found =  this.getPresenter().getContext().getPolicyBean().
 213  
                                 getParentTargetAccessRules(roleref).size() > 0;
 214  0
                 if (found) {
 215  0
                         JOptionPane.showMessageDialog(
 216  
                                 null,
 217  
                                 getResourceMap().getString(operation + "Role.Dialog.text1")
 218  
                         );
 219  
                 }
 220  0
                 return found;
 221  
         }
 222  
 
 223  
         /**
 224  
          * Removes a role from the hierarchy.
 225  
          * @since 0.3.0
 226  
          */
 227  
         @Action
 228  
         public void removeRole () {
 229  0
                 LOGGER.debug("removeRole");
 230  
 
 231  0
                 final RoleNode selectedNode = this.roleBrowser.getSelectedNode();
 232  0
                 if (selectedNode == null) {
 233  0
                         return;
 234  
                 }
 235  
 
 236  
                 // check if role is referenced
 237  0
                 if (checkReferences("remove", this.roleBrowser.getSelectedNode().getRole())) {
 238  0
                         return;
 239  
                 }
 240  
 
 241  0
                 int n = JOptionPane.showConfirmDialog(
 242  
                         null,
 243  
                         getResourceMap().getString("removeRole.Dialog.text2"),
 244  
                         getResourceMap().getString("removeRole.Dialog.title"),
 245  
                         JOptionPane.YES_NO_OPTION
 246  
                 );
 247  
 
 248  0
                 if (n == 0) {
 249  0
                         this.getPresenter().removeRole(
 250  
                                 selectedNode.toString()
 251  
                         );
 252  
                 }
 253  0
         }
 254  
 
 255  
         /**
 256  
          * Renames a role.
 257  
          * @since 0.3.0
 258  
          */
 259  
         @Action
 260  
         public void renameRole () {
 261  0
                 LOGGER.debug("editRole");
 262  
 
 263  0
                 if (this.roleBrowser.getSelectedNode() != null) {
 264  
 
 265  
                         // check if role is referenced
 266  0
                         if (checkReferences("rename", this.roleBrowser.getSelectedNode().getRole())) {
 267  0
                                 return;
 268  
                         }
 269  
 
 270  0
                         String s = (String) JOptionPane.showInputDialog(
 271  
                                 null,
 272  
                                 getResourceMap().getString("renameRole.Dialog.text2"),
 273  
                                 getResourceMap().getString("renameRole.Dialog.title"),
 274  
                                 JOptionPane.PLAIN_MESSAGE,
 275  
                                 null,
 276  
                                 null,
 277  
                                 this.roleBrowser.getSelectedNode().toString()
 278  
                         );
 279  0
                         if (s != null) {
 280  0
                                 this.getPresenter().renameRole(this.roleBrowser.getSelectedNode().toString(), s);
 281  
                         }
 282  
                 }
 283  0
         }
 284  
 
 285  
         /**
 286  
          * @since 0.3.0
 287  
          */
 288  
         public void updateTree () {
 289  0
                 int[] selectionRows = this.tree.getSelectionRows();
 290  0
                 final RoleHierarchyBean roleHierarchyBean = getPresenter().getRoleHierarchyBean();
 291  0
                 this.tree.setModel(
 292  
                         new DefaultTreeModel(
 293  
                                 new RoleNode(roleHierarchyBean)
 294  
                         )
 295  
                 );
 296  0
                 for (int i = 0; i < this.tree.getRowCount(); i++) {
 297  0
                         this.tree.expandRow(i);
 298  
                 }
 299  0
                 if (
 300  
                         selectionRows != null &&
 301  
                         selectionRows.length > 0 &&
 302  
                         selectionRows[0] >= 0 &&
 303  
                         selectionRows[0] < this.tree.getRowCount()) {
 304  0
                         this.tree.setSelectionPath(this.tree.getPathForRow(selectionRows[0]));
 305  
                 }
 306  0
         }
 307  
 
 308  
         /**
 309  
          * Returns the parents of a role.
 310  
          * @param roleNode the role whose parents we get.
 311  
          * @param result the result.
 312  
          * @since 0.3.0
 313  
          */
 314  
         public void getParents (RoleNode roleNode, List<RoleNode> result) {
 315  0
                 searchParents((RoleNode) this.tree.getModel().getRoot(), roleNode, result);
 316  0
         }
 317  
 
 318  
         /**
 319  
          * Sets the tree selection path.
 320  
          * @param node whose path is going to be selected.
 321  
          * @since 0.3.0
 322  
          */
 323  
         public void setSelectionPath (RoleNode node) {
 324  0
                 this.tree.setSelectionPath(recreatePath(node));
 325  0
         }
 326  
 
 327  
         //---- AbstractEditor
 328  
 
 329  
         /**
 330  
          * @since 0.3.0
 331  
          */
 332  
         @Override
 333  
         protected void bind (BindingGroup bindings) {
 334  0
                 getPresenter().getRoleHierarchyBean().addPropertyChangeListener(
 335  
                         this.propertyChangeListener
 336  
                 );
 337  0
         }
 338  
 
 339  
         /**
 340  
          * @since 0.3.0
 341  
          */
 342  
         private TreePath recreatePath (RoleNode node) {
 343  0
                 List<RoleNode> reversedPath = new ArrayList<RoleNode>();
 344  
                 do {
 345  0
                         reversedPath.add(node);
 346  0
                         node = (RoleNode) node.getParent();
 347  0
                 } while (node != null);
 348  0
                 Object[] pathArray = new Object[reversedPath.size()];
 349  0
                 for (int i = 0; i < reversedPath.size(); i++) {
 350  0
                         pathArray[i] = reversedPath.get(reversedPath.size() - 1 - i);
 351  
                 }
 352  0
                 return new TreePath(pathArray);
 353  
         }
 354  
 
 355  
         /**
 356  
          * @since 0.3.0
 357  
          */
 358  
         @SuppressWarnings("unchecked")
 359  
         private void searchParents (RoleNode thisNode, RoleNode childNode, List<RoleNode> result) {
 360  0
                 for (Object o : Collections.list(thisNode.children())) {
 361  0
                         RoleNode childOfThis = (RoleNode) o;
 362  0
                         if (childNode != null && childOfThis.toString().equals(childNode.toString())) {
 363  0
                                 result.add(thisNode);
 364  
                         }
 365  0
                         searchParents(childOfThis, childNode, result);
 366  0
                 }
 367  0
         }
 368  
 
 369  
         //---- AbstractView
 370  
 
 371  
         /**
 372  
          * @since 0.3.0
 373  
          */
 374  
         @Override
 375  
         public Object[] getTitleParameters () {
 376  0
                 return new Object[] {getPresenter().getRoleHierarchyBean().getIdentity()};
 377  
         }
 378  
 
 379  
 
 380  
         //---- View
 381  
 
 382  
         /**
 383  
          * @since 0.3.0
 384  
          */
 385  
         @Override
 386  
         public void fillContentPane (JPanel panel) {
 387  
 
 388  0
                 this.tree.setCellRenderer(new RoleNodeRenderer());
 389  
 
 390  0
                 final FormLayout layout = new FormLayout(
 391  
                         "8dlu, fill:pref:grow, 8dlu, pref, 8dlu", "8dlu, pref, 8dlu, fill:pref:grow, 8dlu"
 392  
                 );
 393  
 
 394  0
                 panel.setLayout(layout);
 395  0
                 CellConstraints cc = new CellConstraints();
 396  0
                 panel.add(toolBar("rolesToolBar"), cc.xyw(2, 2, 3));
 397  
 
 398  0
                 getActionMap().get("includeRole").setEnabled(false);
 399  0
                 getActionMap().get("detachRole").setEnabled(false);
 400  
 
 401  0
                 getActionMap().get("removeRole").setEnabled(false);
 402  0
                 getActionMap().get("renameRole").setEnabled(false);
 403  
 
 404  0
                 this.tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
 405  0
                 this.tree.addTreeSelectionListener(new TreeSelectionListener() {
 406  
 
 407  0
                         public void valueChanged (TreeSelectionEvent e) {
 408  0
                                 RoleHierarchyEditor.this.roleBrowser.setSelectedNode(
 409  
                                         ((RoleNode) e.getPath().getLastPathComponent())
 410  
                                 );
 411  0
                                 getActionMap().get("includeRole").setEnabled(e.getPath().getPathCount() > 1);
 412  0
                                 getActionMap().get("detachRole").setEnabled(e.getPath().getPathCount() > 2);
 413  
 
 414  0
                                 RoleHierarchyEditor.this.tree.getRowForPath(e.getPath());
 415  
 
 416  0
                                 getActionMap().get("removeRole").setEnabled(
 417  
                                         e.getPath().getPathCount() == 2 &&
 418  
                                         RoleHierarchyEditor.this.roleBrowser.getSelectedNode().isLeaf()
 419  
                                 );
 420  0
                                 getActionMap().get("renameRole").setEnabled(e.getPath().getPathCount() > 1);
 421  0
                         }
 422  
 
 423  
                 });
 424  
 
 425  0
                 panel.add(new JScrollPane(this.tree), cc.xy(2, 4));
 426  
 
 427  0
                 this.tree.setRootVisible(false);
 428  
 
 429  0
                 updateTree();
 430  
 
 431  0
                 panel.add(this.roleBrowser, cc.xy(4, 4));
 432  
 
 433  0
         }
 434  
 
 435  
 
 436  
         //---- AnchestorListener
 437  
 
 438  
         /**
 439  
          * @since 0.3.0
 440  
          */
 441  
         public void ancestorAdded (AncestorEvent event) {
 442  
                 // this is empty because only ancestorRemoved is needed
 443  0
         }
 444  
 
 445  
         /**
 446  
          * @since 0.3.0
 447  
          */
 448  
         public void ancestorMoved (AncestorEvent event) {
 449  
                 // this is empty because only ancestorRemoved is needed
 450  0
         }
 451  
 
 452  
         /**
 453  
          * @since 0.3.0
 454  
          */
 455  
         public void ancestorRemoved (AncestorEvent event) {
 456  0
                 getPresenter().getRoleHierarchyBean().removePropertyChangeListener(
 457  
                         this.propertyChangeListener
 458  
                 );
 459  0
         }
 460  
 }
 461  
 
 462  
 /**
 463  
  * Renders the tree nodes only with a {@link String}.
 464  
  * @since 0.3.0
 465  
  */
 466  
 @SuppressWarnings("serial")
 467  0
 class RoleNodeRenderer extends JLabel implements TreeCellRenderer {
 468  
 
 469  
         //---- State
 470  
 
 471  
         /**
 472  
          * @since 0.3.0
 473  
          */
 474  0
         private JTable  dummy4SelectionColors = new JTable();
 475  
 
 476  
         //---- TreeCellRenderer
 477  
 
 478  
         /**
 479  
          * @since 0.3.0
 480  
          */
 481  
         public Component getTreeCellRendererComponent (
 482  
                 JTree tree,
 483  
                 Object value,
 484  
                 boolean isSelected,
 485  
                 boolean isExpanded,
 486  
                 boolean isLeaf,
 487  
                 int row,
 488  
                 boolean hasFocus) {
 489  
 
 490  0
                 setOpaque(true);
 491  
 
 492  0
                 if (isSelected) {
 493  0
                         setForeground(this.dummy4SelectionColors.getSelectionForeground());
 494  0
                         setBackground(this.dummy4SelectionColors.getSelectionBackground());
 495  
                 } else {
 496  0
                         setForeground(this.dummy4SelectionColors.getForeground());
 497  0
                         setBackground(this.dummy4SelectionColors.getBackground());
 498  
                 }
 499  0
                 setText(((TreeNode) value).toString());
 500  0
                 return this;
 501  
         }
 502  
 }
 503  
 
 504  
 /**
 505  
  *
 506  
  * @since 0.3.0
 507  
  */
 508  
 @SuppressWarnings("serial")
 509  0
 class RoleBrowser extends JComponent {
 510  
 
 511  
         //---- Classes
 512  
 
 513  
         /**
 514  
          * @since 0.3.0
 515  
          */
 516  0
         class ParentsTableModel extends AbstractTableModel {
 517  
 
 518  
                 //---- Methods
 519  
 
 520  
                 /**
 521  
                  *
 522  
                  * @since 0.3.0
 523  
                  */
 524  
                 public void update () {
 525  0
                         this.fireTableDataChanged();
 526  0
                 }
 527  
 
 528  
                 //---- AbstractTableModel
 529  
 
 530  
                 /**
 531  
                  * @since 0.3.0
 532  
                  */
 533  
                 public int getColumnCount () {
 534  0
                         return 1;
 535  
                 }
 536  
 
 537  
                 /**
 538  
                  * @since 0.3.0
 539  
                  */
 540  
                 public int getRowCount () {
 541  0
                         return RoleBrowser.this.parentsList.size();
 542  
                 }
 543  
 
 544  
                 /**
 545  
                  * @since 0.3.0
 546  
                  */
 547  
                 public Object getValueAt (int rowIndex, int columnIndex) {
 548  0
                         return RoleBrowser.this.parentsList.get(rowIndex);
 549  
                 }
 550  
         }
 551  
 
 552  
         /**
 553  
          * @since 0.3.0
 554  
          */
 555  0
         class ChildrenTableModel extends AbstractTableModel {
 556  
 
 557  
                 /**
 558  
                  * @since 0.3.0
 559  
                  */
 560  
                 public int getColumnCount () {
 561  0
                         return 1;
 562  
                 }
 563  
 
 564  
                 /**
 565  
                  * @since 0.3.0
 566  
                  */
 567  
                 public int getRowCount () {
 568  0
                         if (RoleBrowser.this.selectedNode != null) {
 569  0
                                 return RoleBrowser.this.selectedNode.getChildCount();
 570  
                         }
 571  0
                         return 0;
 572  
                 }
 573  
 
 574  
                 /**
 575  
                  * @since 0.3.0
 576  
                  */
 577  
                 public Object getValueAt (int rowIndex, int columnIndex) {
 578  0
                         if (RoleBrowser.this.selectedNode != null) {
 579  0
                                 return RoleBrowser.this.selectedNode.getChildAt(rowIndex);
 580  
                         }
 581  0
                         return null;
 582  
                 }
 583  
 
 584  
                 /**                 *
 585  
                  * @since 0.3.0
 586  
                  */
 587  
                 public void update () {
 588  0
                         this.fireTableDataChanged();
 589  0
                 }
 590  
         }
 591  
 
 592  
         /**
 593  
          *          * @since 0.3.0
 594  
          */
 595  
         class NoHeaderJTable extends JTable {
 596  
 
 597  
                 /**
 598  
                  * @since 0.3.0
 599  
                  */
 600  0
                 public NoHeaderJTable (TableModel dm) {
 601  0
                         super(dm);
 602  0
                 }
 603  
 
 604  
                 /**
 605  
                  * Disables the header view of this table.
 606  
                  *
 607  
                  * @since 0.3.0
 608  
                  */
 609  
                 @Override
 610  
                 protected void configureEnclosingScrollPane () {
 611  0
                         Container p = getParent();
 612  0
                         if (p instanceof JViewport) {
 613  0
                                 Container gp = p.getParent();
 614  0
                                 if (gp instanceof JScrollPane) {
 615  0
                                         JScrollPane scrollPane = (JScrollPane) gp;
 616  
                                         // Make certain we are the viewPort's view and not, for
 617  
                                         // example, the rowHeaderView of the scrollPane -
 618  
                                         // an implementor of fixed columns might do this.
 619  0
                                         JViewport viewport = scrollPane.getViewport();
 620  0
                                         if (viewport == null || viewport.getView() != this) {
 621  0
                                                 return;
 622  
                                         }
 623  
                                         // scrollPane.setColumnHeaderView(getTableHeader());
 624  
                                         // scrollPane.getViewport().setBackingStoreEnabled(true);
 625  0
                                         Border border = scrollPane.getBorder();
 626  0
                                         if (border == null || border instanceof UIResource) {
 627  0
                                                 scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
 628  
                                         }
 629  
                                 }
 630  
                         }
 631  0
                 }
 632  
         }
 633  
 
 634  
         //---- State
 635  
 
 636  
         /**
 637  
          * @since 0.3.0
 638  
          */
 639  0
         private ChildrenTableModel childrenTableModel = new ChildrenTableModel();
 640  
 
 641  
         /**
 642  
          * @since 0.3.0
 643  
          */
 644  0
         private JTable childrenTable = new NoHeaderJTable(this.childrenTableModel);
 645  
 
 646  
         /**
 647  
          * @since 0.3.0
 648  
          */
 649  0
         private List<RoleNode> parentsList = new ArrayList<RoleNode>();
 650  
 
 651  
         /**
 652  
          * @since 0.3.0
 653  
          */
 654  0
         private ParentsTableModel parentTableModel = new ParentsTableModel();
 655  
 
 656  
         /**
 657  
          * @since 0.3.0
 658  
          */
 659  0
         private JTable parentTable = new NoHeaderJTable(RoleBrowser.this.parentTableModel);
 660  
 
 661  
         /**
 662  
          * @since 0.3.0
 663  
          */
 664  
         private RoleNode selectedNode;
 665  
 
 666  
         /**
 667  
          * @since 0.3.0
 668  
          */
 669  
         private RoleHierarchyEditor roleHierarchyEditor;
 670  
 
 671  
         //---- Constructors
 672  
 
 673  
         /**
 674  
          * @since 0.3.0
 675  
          */
 676  0
         protected RoleBrowser (RoleHierarchyEditor roleHierarchyEditor) {
 677  0
                 this.roleHierarchyEditor = roleHierarchyEditor;
 678  
 
 679  0
                 setLayout(new FormLayout("fill:pref", "10dlu, 150dlu, 10dlu, fill:pref:grow"));
 680  0
                 CellConstraints cc = new CellConstraints();
 681  
 
 682  0
                 add(new JLabel("super-roles:"), cc.xy(1, 1));
 683  0
                 this.parentTable.getSelectionModel().setSelectionMode(
 684  
                         ListSelectionModel.SINGLE_SELECTION
 685  
                 );
 686  0
                 this.parentTable.getSelectionModel().addListSelectionListener(
 687  
                         new ListSelectionListener() {
 688  0
                                 public void valueChanged (ListSelectionEvent e) {
 689  0
                                         if (!e.getValueIsAdjusting() && e.getFirstIndex() >= 0) {
 690  0
                                                 RoleBrowser.this.roleHierarchyEditor.setSelectionPath(
 691  
                                                         ((RoleNode) RoleBrowser.this.parentTable.
 692  
                                                                 getValueAt(e.getFirstIndex(), 0))
 693  
                                                 );
 694  
                                         }
 695  0
                                 }
 696  
                         }
 697  
                 );
 698  0
                 add(new JScrollPane(this.parentTable), cc.xy(1, 2));
 699  
 
 700  0
                 add(new JLabel("sub-roles:"), cc.xy(1, 3));
 701  0
                 this.childrenTable.getSelectionModel().setSelectionMode(
 702  
                         ListSelectionModel.SINGLE_SELECTION
 703  
                 );
 704  0
                 this.childrenTable.getSelectionModel().addListSelectionListener(
 705  
                         new ListSelectionListener() {
 706  0
                                 public void valueChanged (ListSelectionEvent e) {
 707  0
                                         if (!e.getValueIsAdjusting() && e.getFirstIndex() >= 0) {
 708  0
                                                 RoleBrowser.this.roleHierarchyEditor.setSelectionPath(
 709  
                                                         ((RoleNode) RoleBrowser.this.childrenTable.
 710  
                                                                 getValueAt(e.getFirstIndex(), 0))
 711  
                                                 );
 712  
                                         }
 713  0
                                 }
 714  
                         }
 715  
                 );
 716  
 
 717  0
                 add(new JScrollPane(this.childrenTable), cc.xy(1, 4));
 718  0
         }
 719  
 
 720  
         //---- Methods
 721  
 
 722  
         /**
 723  
          * @since 0.3.0
 724  
          */
 725  
         public void setSelectedNode (RoleNode roleNode) {
 726  0
                 this.selectedNode = roleNode;
 727  0
                 this.parentsList.clear();
 728  0
                 this.roleHierarchyEditor.getParents(roleNode, this.parentsList);
 729  0
                 this.parentTableModel.update();
 730  0
                 this.childrenTableModel.update();
 731  0
         }
 732  
 
 733  
         /**
 734  
          * @since 0.3.0
 735  
          */
 736  
         public RoleNode getSelectedNode () {
 737  0
                 return this.selectedNode;
 738  
         }
 739  
 }
 740  
 
 741  
 /**
 742  
  * @since 0.3.0
 743  
  */
 744  
 class RoleNode implements TreeNode {
 745  
 
 746  
         /**
 747  
          * @since 0.3.0
 748  
          */
 749  
         private RoleNode parent;
 750  
 
 751  
         /**
 752  
          * @since 0.3.0
 753  
          */
 754  
         private String role;
 755  
 
 756  
         /**
 757  
          * @since 0.3.0
 758  
          */
 759  
         private List<TreeNode> subRoles;
 760  
 
 761  
         /**
 762  
          * @since 0.3.0
 763  
          */
 764  
         private RoleHierarchyBean hierarchy;
 765  
 
 766  
         //---- Constructors
 767  
 
 768  
         /**
 769  
          * @since 0.3.0
 770  
          */
 771  0
         public RoleNode (RoleHierarchyBean hierarchy, String role, RoleNode parent) {
 772  0
                 this.role = role;
 773  0
                 this.parent = parent;
 774  0
                 this.hierarchy = hierarchy;
 775  0
                 this.subRoles = new ArrayList<TreeNode>();
 776  0
                 final List<String> children = new ArrayList<String>(this.hierarchy.getChildRoles(role));
 777  0
                 Collections.sort(children);
 778  0
                 for (String r : children) {
 779  0
                         this.subRoles.add(new RoleNode(this.hierarchy, r, this));
 780  
                 }
 781  0
         }
 782  
 
 783  
         /**
 784  
          * @since 0.3.0
 785  
          */
 786  0
         public RoleNode (RoleHierarchyBean hierarchy) {
 787  0
                 this.role = null;
 788  0
                 this.parent = null;
 789  0
                 this.hierarchy = hierarchy;
 790  0
                 this.subRoles = new ArrayList<TreeNode>();
 791  0
                 for (String r : hierarchy.getRootRoles()) {
 792  0
                         this.subRoles.add(new RoleNode(this.hierarchy, r, this));
 793  
                 }
 794  0
         }
 795  
 
 796  
         //---- TreeNode
 797  
 
 798  
         /**
 799  
          * @since 0.3.0
 800  
          */
 801  
         @SuppressWarnings("unchecked")
 802  
         public Enumeration children () {
 803  0
                 return Collections.enumeration(this.subRoles);
 804  
         }
 805  
 
 806  
         /**
 807  
          * @since 0.3.0
 808  
          */
 809  
         public boolean getAllowsChildren () {
 810  0
                 return true;
 811  
         }
 812  
 
 813  
         /**
 814  
          * @since 0.3.0
 815  
          */
 816  
         public TreeNode getChildAt (int childIndex) {
 817  0
                 return this.subRoles.get(childIndex);
 818  
         }
 819  
 
 820  
         /**
 821  
          * @since 0.3.0
 822  
          */
 823  
         public int getChildCount () {
 824  0
                 return this.subRoles.size();
 825  
         }
 826  
 
 827  
         /**
 828  
          * @since 0.3.0
 829  
          */
 830  
         public int getIndex (TreeNode node) {
 831  0
                 return this.subRoles.indexOf(node);
 832  
         }
 833  
 
 834  
         /**
 835  
          * @since 0.3.0
 836  
          */
 837  
         public TreeNode getParent () {
 838  0
                 return this.parent;
 839  
         }
 840  
 
 841  
         /**
 842  
          * @since 0.3.0
 843  
          */
 844  
         public String getRole () {
 845  0
                 return this.role;
 846  
         }
 847  
 
 848  
         /**
 849  
          * @since 0.3.0
 850  
          */
 851  
         public boolean isLeaf () {
 852  0
                 return this.subRoles.size() == 0;
 853  
         }
 854  
 
 855  
         /**
 856  
          * @since 0.3.0
 857  
          */
 858  
         @Override
 859  
         public String toString () {
 860  0
                 if (this.role == null) {
 861  0
                         return "";
 862  
                 }
 863  0
                 return this.role;
 864  
         }
 865  
 
 866  
 }
 867