Coverage Report - org.openpermis.editor.policy.gui.checklist.CheckListModel
 
Classes in this File Line Coverage Branch Coverage Complexity
CheckListModel
69%
16/23
N/A
1.367
CheckListModel$1
N/A
N/A
1.367
CheckListModel$ColumnType
77%
14/18
70%
7/10
1.367
CheckListModel$ColumnType$1
22%
2/9
0%
0/4
1.367
CheckListModel$ColumnType$2
66%
2/3
N/A
1.367
CheckListModel$PoolListener
76%
13/17
100%
6/6
1.367
CheckListModel$SelectionListener
100%
3/3
N/A
1.367
 
 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.gui.checklist;
 11  
 
 12  
 import java.util.List;
 13  
 import java.util.ListIterator;
 14  
 
 15  
 import javax.swing.table.AbstractTableModel;
 16  
 
 17  
 import org.jdesktop.observablecollections.ObservableList;
 18  
 import org.jdesktop.observablecollections.ObservableListListener;
 19  
 
 20  
 import org.openpermis.editor.policy.gui.binding.ObservableListAdapter;
 21  
 import org.openpermis.policy.Role;
 22  
 
 23  
 
 24  
 /**
 25  
  * Creates a model that manages a pool of items and a selection list from the pool.
 26  
  * @param <T> type of the items in the check list model.
 27  
  * @since 0.1.0
 28  
  */
 29  24
 public class CheckListModel<T>
 30  
         extends AbstractTableModel
 31  
 {
 32  
 
 33  
         //---- State
 34  
         
 35  
         /**
 36  
          * @since 0.3.0
 37  
          */
 38  
         private static final long serialVersionUID = 4791486544723792077L;
 39  
 
 40  
         /**
 41  
          * The pool of available items that can be chosen.
 42  
          * @since 0.1.0
 43  
          */
 44  
         private final ObservableList<T> pool;
 45  
         
 46  
         /**
 47  
          * Listener that synchronizes the state of the table model and the pool list.
 48  
          * @since 0.1.0
 49  
          */
 50  
         private final PoolListener poolListener;
 51  
         
 52  
         /**
 53  
          * The currently selected items from the pool.
 54  
          * @since 0.1.0
 55  
          */
 56  
         private final ObservableList<T> selection;
 57  
         
 58  
         /**
 59  
          * Listener that refreshes the check list whenever a change occurs.
 60  
          * @since 0.1.0
 61  
          */
 62  
         private final SelectionListener selectionListener;
 63  
         
 64  
         //---- Constructors
 65  
         
 66  
         /**
 67  
          * Creates a new check list model.
 68  
          * @param pool the  poolof available items that can be chosen.
 69  
          * @param selection the currently selected items from the pool.
 70  
          * @since 0.1.0
 71  
          */
 72  7
         public CheckListModel (ObservableList<T> pool, ObservableList<T> selection) {
 73  7
                 this.pool = pool;
 74  7
                 this.poolListener = new PoolListener();
 75  7
                 this.selection = selection;
 76  7
                 this.selectionListener = new SelectionListener();
 77  7
         }
 78  
         
 79  
         //---- Methods
 80  
         
 81  
         /**
 82  
          * Adds listeners to synchronize the list with the table model.
 83  
          * @since 0.1.0
 84  
          */
 85  
         public void configureListeners () {
 86  7
                 this.pool.addObservableListListener(this.poolListener);
 87  7
                 this.selection.addObservableListListener(this.selectionListener);
 88  7
         }
 89  
         
 90  
         /**
 91  
          * Removes the listeners to synchronize the list with the table model added in
 92  
          * {@link #configureListeners()}.
 93  
          * @since 0.1.0
 94  
          */
 95  
         public void unconfigureListeners () {
 96  7
                 this.pool.removeObservableListListener(this.poolListener);
 97  7
                 this.selection.removeObservableListListener(this.selectionListener);
 98  7
         }
 99  
         
 100  
         /**
 101  
          * Returns the type of the column at the specified index.
 102  
          * @param columnIndex the index for which to retrieve the column type.
 103  
          * @return the type requested.
 104  
          * @since 0.1.0
 105  
          */
 106  
         private ColumnType getColumnType (int columnIndex) {
 107  320
                 return ColumnType.values()[columnIndex];
 108  
         }
 109  
         
 110  
         /**
 111  
          * Check if the column specified contains the value of the check list model.
 112  
          * @param columnIndex the column to check.
 113  
          * @return {@code true} if it is a value column, {@code false} otherwise.
 114  
          * @since 0.4.0
 115  
          */
 116  
         public boolean isValueColumn (int columnIndex) {
 117  0
                 return getColumnType(columnIndex).isValueType();
 118  
         }
 119  
         
 120  
         //---- TableModel
 121  
         
 122  
         /**
 123  
          * @since 0.1.0
 124  
          */
 125  
         @Override
 126  
         public boolean isCellEditable (int rowIndex, int columnIndex) {
 127  0
                 return getColumnType(columnIndex).isEditable();
 128  
         }
 129  
         
 130  
         /**
 131  
          * @since 0.1.0
 132  
          */
 133  
         @Override
 134  
         public Class<?> getColumnClass (int columnIndex) {
 135  0
                 return getColumnType(columnIndex).getColumnClass();
 136  
         }
 137  
         
 138  
         /**
 139  
          * @since 0.1.0
 140  
          */
 141  
         @Override
 142  
         public String getColumnName (int columnIndex) {
 143  0
                 return getColumnType(columnIndex).getColumnName();
 144  
         }
 145  
         
 146  
         /**
 147  
          * @since 0.1.0
 148  
          */
 149  
         public int getColumnCount () {
 150  0
                 return ColumnType.values().length;
 151  
         }
 152  
         
 153  
         /**
 154  
          * @since 0.1.0
 155  
          */
 156  
         public int getRowCount () {
 157  9
                 return this.pool.size();
 158  
         }
 159  
         
 160  
         /**
 161  
          * @since 0.1.0
 162  
          */
 163  
         public Object getValueAt (int rowIndex, int columnIndex) {
 164  320
                 return getColumnType(columnIndex).getValue(rowIndex, this.pool, this.selection);
 165  
         }
 166  
         
 167  
         /**
 168  
          * @since 0.1.0
 169  
          */
 170  
         @Override
 171  
         public void setValueAt (Object value, int rowIndex, int columnIndex) {
 172  0
                 getColumnType(columnIndex).setValue(rowIndex, value, this.pool, this.selection);
 173  0
         }
 174  
 
 175  
         //---- ColumnType
 176  
         
 177  
         /**
 178  
          * Describes the type of a column, including getters and setters.
 179  
          * @since 0.1.0
 180  
          */
 181  323
         enum ColumnType {
 182  
                 
 183  1
                 CHECKBOX("Checkbox", Boolean.class, true, false) {
 184  
                         @Override
 185  
                         public Object getValue (int rowIndex, List<?> itemPool, List<?> selectionList) {
 186  160
                                 return Boolean.valueOf(contains(selectionList, itemPool.get(rowIndex)));
 187  
                         }
 188  
                         @Override
 189  1
                         public <T> void setValue (
 190  
                                 int rowIndex, Object value, List<T> itemPool, List<T> selectionList
 191  
                         ) {
 192  0
                                 final boolean add = Boolean.TRUE.equals(value);
 193  0
                                 final T item = itemPool.get(rowIndex);
 194  0
                                 if (add != contains(selectionList, item)) {
 195  0
                                         if (add) {
 196  0
                                                 selectionList.add(item);
 197  
                                         } else {
 198  0
                                                 selectionList.remove(indexOf(selectionList, item));
 199  
                                         }
 200  
                                 }
 201  0
                         }
 202  
                 },
 203  1
                 ITEM("Item", Object.class, false, true) {
 204  
                         @Override
 205  
                         public Object getValue (int rowIndex, List<?> itemPool, List<?> selectionList) {
 206  160
                                 return itemPool.get(rowIndex);
 207  
                         }
 208  
                         @Override
 209  1
                         public <T> void setValue (
 210  
                                 int rowIndex, Object value, List<T> itemPool, List<T> selectionList
 211  
                         ) {
 212  0
                                 throw new IllegalStateException(
 213  
                                         "Editing of column [" + getColumnName() + "] not supported."
 214  
                                 );
 215  
                         }
 216  
                 };
 217  
                 
 218  
                 //---- State
 219  
                 
 220  
                 private final String columnName;
 221  
                 private final Class<?> columnClass;
 222  
                 private final boolean editable;
 223  
                 private final boolean valueType;
 224  
                 
 225  
                 //---- Constructors
 226  
                 
 227  
                 private ColumnType (
 228  
                         String columnName, Class<?> columnClass, boolean editable, boolean valueType
 229  2
                 ) {
 230  2
                         this.columnName = columnName;
 231  2
                         this.columnClass = columnClass;
 232  2
                         this.editable = editable;
 233  2
                         this.valueType = valueType;
 234  2
                 }
 235  
                 
 236  
                 //---- Methods
 237  
                 
 238  
                 /**
 239  
                  * Returns the index of the specified item in the given list.
 240  
                  * @param list the list to find the item in.
 241  
                  * @param item the item to search for by identity.
 242  
                  * @return the index requested or -1 if there is no such item.
 243  
                  * @since 0.1.0
 244  
                  */
 245  
                 protected int indexOf (List<?> list, Object item) {
 246  955
                         for (int i = 0; i < list.size(); i++) {
 247  846
                                 if (
 248  
                                         // The class Role role has an implementation of equals.
 249  
                                         list.get(i) instanceof Role && list.get(i).equals(item)
 250  
                                         || list.get(i) == item
 251  
                                 ) {
 252  51
                                         return i;
 253  
                                 }
 254  
                         }
 255  109
                         return -1;
 256  
                 }
 257  
                 
 258  
                 /**
 259  
                  * Checks if the specified item is in the given list.
 260  
                  * @param list the list to search.
 261  
                  * @param item the item to check.
 262  
                  * @return {@code true} if the item is in the list, {@code false} otherwise.
 263  
                  * @since 0.1.0
 264  
                  */
 265  
                 protected boolean contains (List<?> list, Object item) {
 266  160
                         return indexOf(list, item) != -1;
 267  
                 }
 268  
                 
 269  
                 /**
 270  
                  * Returns the value of this column at the specified row index.
 271  
                  * @param rowIndex the index for which to retrieve the value.
 272  
                  * @param itemPool the pool of items.
 273  
                  * @param selectionList the list of currently selected items.
 274  
                  * @return the value at the given row/column.
 275  
                  * @since 0.1.0
 276  
                  */
 277  
                 public abstract Object getValue (int rowIndex, List<?> itemPool, List<?> selectionList);
 278  
                 
 279  
                 /**
 280  
                  * Sets the value of this column at the specified row index.
 281  
                  * @param rowIndex the index for which to set the value.
 282  
                  * @param itemPool the pool of items.
 283  
                  * @param selectionList the list of currently selected items.
 284  
                  * @since 0.1.0
 285  
                  */
 286  
                 public abstract <T> void setValue (
 287  
                         int rowIndex, Object value, List<T> itemPool, List<T> selectionList
 288  
                 );
 289  
                 
 290  
                 /**
 291  
                  * The name of this column.
 292  
                  * @return the name of this column.
 293  
                  * @since 0.1.0
 294  
                  */
 295  
                 public String getColumnName () {
 296  0
                         return this.columnName;
 297  
                 }
 298  
                 
 299  
                 /**
 300  
                  * The value class of this column.
 301  
                  * @return the value class of this column.
 302  
                  * @since 0.1.0
 303  
                  */
 304  
                 public Class<?>        getColumnClass () {
 305  0
                         return this.columnClass;
 306  
                 }
 307  
                 
 308  
                 /**
 309  
                  * @return the editable.
 310  
                  * @since 0.1.0
 311  
                  */
 312  
                 public boolean isEditable () {
 313  0
                         return this.editable;
 314  
                 }
 315  
                 
 316  
                 /**
 317  
                  * Check if this column denotes a type that reflects a value.
 318  
                  * @since 0.4.0
 319  
                  */
 320  
                 public boolean isValueType () {
 321  0
                         return this.valueType;
 322  
                 }
 323  
                 
 324  
         }
 325  
         
 326  
         //---- PoolListener
 327  
 
 328  
         /**
 329  
          * Synchronizes the check list model if a change in the pool list occurs.
 330  
          * @since 0.1.0
 331  
          */
 332  
         @SuppressWarnings("unchecked")
 333  14
         private class PoolListener
 334  
                 implements ObservableListListener
 335  
         {
 336  
 
 337  
                 /**
 338  
                  * @since 0.1.0
 339  
                  */
 340  
                 public void listElementPropertyChanged (ObservableList list, int index) {
 341  0
                         CheckListModel.this.fireTableRowsUpdated(index, index);
 342  0
                 }
 343  
 
 344  
                 /**
 345  
                  * @since 0.1.0
 346  
                  */
 347  
                 public void listElementReplaced (ObservableList list, int index, Object oldElement) {
 348  0
                         CheckListModel.this.fireTableRowsUpdated(index, index);
 349  0
                 }
 350  
 
 351  
                 /**
 352  
                  * @since 0.1.0
 353  
                  */
 354  
                 public void listElementsAdded (ObservableList list, int index, int length) {
 355  4
                         CheckListModel.this.fireTableRowsInserted(index, index + length);
 356  4
                 }
 357  
 
 358  
                 /**
 359  
                  * @since 0.1.0
 360  
                  */
 361  
                 public void listElementsRemoved (ObservableList list, int index, List oldElements) {
 362  5
                         for (final Object obj : oldElements) {
 363  24
                                 final ListIterator<T> iterator = CheckListModel.this.selection.listIterator();
 364  119
                                 while (iterator.hasNext()) {
 365  95
                                         final T item = iterator.next();
 366  95
                                         if (obj == item) {
 367  9
                                                 iterator.remove();
 368  
                                         }
 369  95
                                 }
 370  24
                         }
 371  5
                         CheckListModel.this.fireTableDataChanged();
 372  5
                 }
 373  
                 
 374  
         }
 375  
         
 376  
         //---- SelectionListener
 377  
         
 378  
         /**
 379  
          * Synchronizes the check list model if a change in the selection list occurs.
 380  
          * @since 0.1.0
 381  
          */
 382  
         @SuppressWarnings("unchecked")
 383  14
         private class SelectionListener
 384  
                 extends ObservableListAdapter
 385  
         {
 386  
                 
 387  
                 /**
 388  
                  * @since 0.3.0
 389  
                  */
 390  
                 @Override
 391  
                 protected void listChanged (ObservableList list) {
 392  18
                         CheckListModel.this.fireTableDataChanged();
 393  18
                 }
 394  
                 
 395  
         }
 396  
         
 397  
 }