Coverage Report - org.kuali.student.lum.common.client.lo.CategoryManagementTable
 
Classes in this File Line Coverage Branch Coverage Complexity
CategoryManagementTable
0%
0/193
0%
0/82
2.548
CategoryManagementTable$1
0%
0/7
0%
0/2
2.548
CategoryManagementTable$2
0%
0/9
N/A
2.548
CategoryManagementTable$CategoryRow
0%
0/7
N/A
2.548
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.lum.common.client.lo;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashSet;
 20  
 import java.util.List;
 21  
 
 22  
 import org.kuali.student.common.search.dto.SearchRequest;
 23  
 import org.kuali.student.common.search.dto.SearchResult;
 24  
 import org.kuali.student.common.search.dto.SearchResultCell;
 25  
 import org.kuali.student.common.search.dto.SearchResultRow;
 26  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 27  
 import org.kuali.student.common.ui.client.mvc.Callback;
 28  
 import org.kuali.student.common.ui.client.service.SearchRpcService;
 29  
 import org.kuali.student.common.ui.client.service.SearchRpcServiceAsync;
 30  
 import org.kuali.student.common.ui.client.service.ServerPropertiesRpcService;
 31  
 import org.kuali.student.common.ui.client.service.ServerPropertiesRpcServiceAsync;
 32  
 import org.kuali.student.common.ui.client.widgets.searchtable.ResultRow;
 33  
 import org.kuali.student.common.ui.client.widgets.table.scroll.Column;
 34  
 import org.kuali.student.common.ui.client.widgets.table.scroll.DefaultTableModel;
 35  
 import org.kuali.student.common.ui.client.widgets.table.scroll.Row;
 36  
 import org.kuali.student.common.ui.client.widgets.table.scroll.Table;
 37  
 import org.kuali.student.lum.lo.dto.LoCategoryInfo;
 38  
 
 39  
 import com.google.gwt.core.client.GWT;
 40  
 import com.google.gwt.user.client.Window;
 41  
 import com.google.gwt.user.client.ui.Composite;
 42  
 import com.google.gwt.user.client.ui.FlowPanel;
 43  
 
 44  
 /**
 45  
  * This is a description of what this class does - Gary Struthers don't forget to fill this in. 
 46  
  * 
 47  
  * @author Kuali Student Team (gstruthers@berkeley.edu)
 48  
  *
 49  
  */
 50  0
 public class CategoryManagementTable extends Composite {
 51  0
     static String NAME_COLUMN_HEADER = "Category";
 52  0
     static String TYPE_COLUMN_HEADER = "Type";
 53  0
     static String STATE_COLUMN_HEADER = "State";
 54  0
     static String ID_COLUMN_KEY = "id";
 55  0
     static String NAME_COLUMN_KEY = "name";
 56  0
     static String TYPE_COLUMN_KEY = "type";
 57  0
     static String TYPE_NAME_COLUMN_KEY = "typeName";
 58  0
     static String STATE_COLUMN_KEY = "state";
 59  0
     private List<ResultRow> resultRows = new ArrayList<ResultRow>();
 60  0
     private DefaultTableModel model = new DefaultTableModel();        //Contains Category rows that go into 'Select Categories' KSLightBox [KSLAB-2091]
 61  0
     private Table table = new Table();
 62  
     //private GenericTableModel<ResultRow> tableModel = new GenericTableModel<ResultRow>(resultRows);
 63  
     //private PagingScrollTableBuilder<ResultRow> builder = new PagingScrollTableBuilder<ResultRow>();
 64  
     //protected PagingScrollTable<ResultRow> pagingScrollTable;
 65  0
     private FlowPanel layout = new FlowPanel();
 66  
     private static Boolean displayOnlyActiveCategories; // static global
 67  0
     private boolean hideInactiveCategories = false;
 68  
 
 69  0
     private SearchRpcServiceAsync searchDispatcherAsync = GWT.create(SearchRpcService.class); //KSLAB-2091
 70  
 
 71  0
     private static ServerPropertiesRpcServiceAsync serverProperties = GWT.create(ServerPropertiesRpcService.class);
 72  
 
 73  
     // Categories to filter out after the are loaded from the backend
 74  
     // See KSLAB-1871
 75  0
     private List<LoCategoryInfo> loCategoriesToFilter = new ArrayList<LoCategoryInfo>();
 76  
     
 77  
     class CategoryRow extends Row{
 78  
             ResultRow row;
 79  
             
 80  0
             public CategoryRow(ResultRow row){
 81  0
                     this.row = row;
 82  0
             }
 83  
                 @Override
 84  
                 public Object getCellData(String columnId) {
 85  0
                         return row.getValue(columnId);
 86  
                 }
 87  
                 @Override
 88  
                 public void setCellData(String columnId, Object newValue) {
 89  0
                         row.setValue(columnId, newValue.toString());                
 90  0
                 }
 91  
                 
 92  
                 public ResultRow getResultRowData(){
 93  0
                         return row;
 94  
                 }
 95  
         }
 96  
     
 97  
     public Table getTable(){
 98  0
             return table;
 99  
     }
 100  
     
 101  
     /**
 102  
      * This method should be called before constructor so config flag is pre-set
 103  
      * only needs to be called once. It's a static flag that only changes when the 
 104  
      * server is started
 105  
      * 
 106  
      */
 107  
     public static void setDisplayOnlyActiveCategories() {
 108  0
         if (null == displayOnlyActiveCategories) {
 109  0
             serverProperties.get("ks.lum.ui.displayOnlyActiveLoCategories", new KSAsyncCallback<String>() {
 110  
                 @Override
 111  
                 public void handleFailure(Throwable caught) {
 112  0
                     GWT.log("get displayOnlyActiveLoCategories failed", caught);
 113  0
                     Window.alert("Failed to get displayOnlyActiveLoCategories setting");
 114  0
                 }
 115  
     
 116  
                 @Override
 117  
                 public void onSuccess(String result) {
 118  0
                     if (result != null) {
 119  0
                         displayOnlyActiveCategories = Boolean.parseBoolean(result);
 120  
                     }
 121  0
                 }
 122  
             });
 123  
         }  
 124  0
     }
 125  
     
 126  
     private void initCategoryManagementTable(boolean isMultiSelect){
 127  0
         layout.setWidth("100%");
 128  0
         table.setWidth("550px");
 129  0
         table.getScrollPanel().setHeight("400px");
 130  0
         initWidget(layout);
 131  0
         createColumnDefs();
 132  0
         if(isMultiSelect){
 133  0
                 model.setMultipleSelectable(true);
 134  0
                 model.installCheckBoxRowHeaderColumn();
 135  
         }
 136  
         else{
 137  0
                 model.setMultipleSelectable(false);
 138  
         }
 139  0
         table.setTableModel(model);
 140  
         
 141  0
         layout.add(table);
 142  0
     }
 143  
     public CategoryManagementTable() {
 144  0
         super();
 145  0
         initCategoryManagementTable(false);
 146  0
     }
 147  
     /**
 148  
      * Constructor that allows us to filter categories.
 149  
      * <p>
 150  
      * Currently used to filter categories that are already in the picker. 
 151  
      * <p>
 152  
      *  See KSLAB-1871
 153  
      *
 154  
      * @param hideInactiveCategories
 155  
      * @param isMultiSelect
 156  
      * @param loCategoriesToFilter categories to filter out
 157  
      */
 158  
     public CategoryManagementTable(boolean hideInactiveCategories, boolean isMultiSelect, List<LoCategoryInfo> loCategoriesToFilter) {
 159  0
         super();
 160  0
         this.hideInactiveCategories = hideInactiveCategories;
 161  0
         this.loCategoriesToFilter = loCategoriesToFilter;  // needed in constructor due to async
 162  0
         initCategoryManagementTable(isMultiSelect);
 163  0
     }
 164  
     /**
 165  
      * This constructs a CategoryManagementTable with an instance option
 166  
      * 
 167  
      * @param hideInactiveCategories
 168  
      */
 169  
     public CategoryManagementTable(boolean hideInactiveCategories, boolean isMultiSelect) {
 170  0
         super();
 171  0
         this.hideInactiveCategories = hideInactiveCategories;
 172  0
         initCategoryManagementTable(isMultiSelect);
 173  0
     }
 174  
     /**
 175  
      * Two flags control whether to show rows with inactive categories and the state column.
 176  
      * hideInactiveCategories can be set per table instance
 177  
      * displayOnlyActiveCategories is set at Lum startup
 178  
      * hideInactiveCategories overrides displayOnlyActiveCategories
 179  
      * @return true to show all rows and State column
 180  
      */
 181  
     public boolean isHideInactiveCategories() {
 182  0
         if(hideInactiveCategories){
 183  0
             return true;
 184  
         } 
 185  0
         if((displayOnlyActiveCategories == null)||( displayOnlyActiveCategories.booleanValue() == false)){
 186  0
             return false;
 187  
         }else {
 188  0
             return true;
 189  
         }
 190  
     }
 191  
     /**
 192  
      * @param show or hide inactive rows and State column 
 193  
      */
 194  
     public void setHideInactiveCategories(boolean show) {
 195  0
         this.hideInactiveCategories = show;
 196  0
     }
 197  
     public void redraw(){
 198  0
             model.clearRows();
 199  0
             for(ResultRow row: resultRows){
 200  0
                     model.addRow(new CategoryRow(row));
 201  
             }
 202  0
             model.fireTableDataChanged();
 203  0
     }
 204  
     
 205  
     public void redraw(List<ResultRow> filteredRows){
 206  0
             model.clearRows();
 207  0
             table.removeAllRows();
 208  0
             for(ResultRow row: filteredRows){
 209  0
                     model.addRow(new CategoryRow(row));
 210  
             }
 211  0
             model.setCurrentIndex(0);
 212  0
             model.fireTableDataChanged();
 213  0
     }
 214  
 
 215  
     public void clearTable(){
 216  0
         resultRows.clear();
 217  0
         redraw();        
 218  0
     }
 219  
     
 220  
     public void removeSelected(){
 221  0
         for(ResultRow r: getSelectedRows()){
 222  0
             resultRows.remove(r);
 223  
         }
 224  0
         this.redraw();
 225  0
     }
 226  
     public List<ResultRow> getAllRows(){
 227  0
         List<ResultRow> rows = new ArrayList<ResultRow>();
 228  0
         for(ResultRow r: resultRows){
 229  0
             rows.add(r);
 230  
         }
 231  0
         return rows;
 232  
     }    
 233  
     public List<ResultRow> getSelectedRows(){
 234  0
         List<ResultRow> rows = new ArrayList<ResultRow>();
 235  0
         List<Row> selectedRows = model.getSelectedRows();
 236  0
         for(Row r: selectedRows){
 237  0
             rows.add(((CategoryRow)r).getResultRowData());
 238  
         }
 239  0
         return rows;
 240  
     }
 241  
     public List<LoCategoryInfo> getSelectedLoCategoryInfos(){
 242  0
         List<LoCategoryInfo> loCategoryInfos = new ArrayList<LoCategoryInfo>();
 243  0
         List<Row> selectedRows = model.getSelectedRows();
 244  0
         if(selectedRows.isEmpty()) {
 245  0
             return loCategoryInfos;
 246  
         }
 247  0
         for(Row r: selectedRows){
 248  0
             LoCategoryInfo loCategoryInfo = new LoCategoryInfo();
 249  0
             loCategoryInfo.setId(r.getCellData(ID_COLUMN_KEY).toString());
 250  0
             loCategoryInfo.setName(r.getCellData(NAME_COLUMN_KEY).toString());
 251  0
             loCategoryInfo.setType(r.getCellData(TYPE_COLUMN_KEY).toString());
 252  0
             loCategoryInfo.setState(r.getCellData(STATE_COLUMN_KEY).toString());
 253  0
             loCategoryInfos.add(loCategoryInfo);
 254  0
         }
 255  0
         return loCategoryInfos;
 256  
     }    
 257  
 
 258  
     public String getSelectedLoCategoryInfoId(){ 
 259  0
         List<Row> selectedRows = model.getSelectedRows();
 260  0
         if(selectedRows.isEmpty()) {
 261  0
             return null;
 262  
         }
 263  0
         String id = null;
 264  0
         for(Row r: selectedRows){
 265  0
             id = r.getCellData(ID_COLUMN_KEY).toString();
 266  0
             break;
 267  
         }
 268  0
         return id;
 269  
 
 270  
     }   
 271  
     
 272  
     private void createColumnDefs() {
 273  
             
 274  0
             Column name = new Column();
 275  0
             name.setName(NAME_COLUMN_HEADER);
 276  0
             name.setId(NAME_COLUMN_KEY);
 277  0
             name.setSortable(false);
 278  0
             model.addColumn(name);
 279  0
             name.setWidth("250px");
 280  
             
 281  0
             Column type = new Column();
 282  0
             type.setName(TYPE_COLUMN_HEADER);
 283  0
             type.setId(TYPE_NAME_COLUMN_KEY);
 284  0
             type.setSortable(false);
 285  0
             model.addColumn(type);
 286  
             
 287  0
         if (!isHideInactiveCategories()) {
 288  0
                 Column state = new Column();
 289  0
                 state.setName(STATE_COLUMN_HEADER);
 290  0
                 state.setId(STATE_COLUMN_KEY);
 291  0
                 state.setSortable(false);
 292  0
                 model.addColumn(state);          
 293  
         }
 294  0
     }
 295  
     
 296  
     /**
 297  
      * 
 298  
      * This method will filter out categories that should be excluded 
 299  
      * from the list (e.g. those already in the picker).
 300  
      * <p>
 301  
      * It is called from the filterResults method.
 302  
      * <p>
 303  
      * See KSLAB-1871
 304  
      * 
 305  
      * @param results
 306  
      * @return
 307  
      */
 308  
     private List<LoCategoryInfo> filterResultsWithExcludedCategories(List<LoCategoryInfo> results){
 309  0
         if (loCategoriesToFilter == null || loCategoriesToFilter.size() == 0){
 310  
             // If nothing to filter just return results passed in
 311  0
             return results;
 312  
         }
 313  0
         List<LoCategoryInfo> filteredResults = new ArrayList<LoCategoryInfo>();
 314  0
         for(LoCategoryInfo result : results) {
 315  0
             boolean shouldExcludeRow = false;
 316  0
             for (LoCategoryInfo toFilter : loCategoriesToFilter) {
 317  0
                 String name = toFilter.getName();
 318  0
                 String type = toFilter.getType();
 319  0
                 if (result.getName().equals(name) && result.getType().equals(type)){
 320  0
                     shouldExcludeRow = true;
 321  0
                     break;
 322  
                 }
 323  0
             } 
 324  0
             if (!shouldExcludeRow){
 325  0
                 filteredResults.add(result);
 326  
             }
 327  0
         }
 328  0
         return filteredResults;
 329  
     }
 330  
 
 331  
     
 332  
     private List<LoCategoryInfo> filterResults(List<LoCategoryInfo> result) {
 333  
 
 334  
        // Filter if already in picker etc
 335  0
        result = filterResultsWithExcludedCategories(result);
 336  
   
 337  0
        if(isHideInactiveCategories()) {
 338  0
             List<LoCategoryInfo> filteredResult = new ArrayList<LoCategoryInfo>();
 339  0
             for(LoCategoryInfo info : result) {
 340  0
                 if (info.getState().equals("active") ) {
 341  0
                     filteredResult.add(info);
 342  
                 }
 343  
             }
 344  0
             return filteredResult;
 345  
         } 
 346  0
         return result;   
 347  
     }
 348  
     
 349  
     public void loadTable(final Callback<Boolean> callback) {
 350  0
             table.displayLoading(true);
 351  
             /* KSLAB-2091
 352  
              * 
 353  
              * This is the new way to initiate a query for loCategories:
 354  
              *                 It is a searchDispatcherAsync call that returns a SearchResult on success;
 355  
              *                         the SearchResult has the necessary CategoryType name info.
 356  
              *                         Furthermore this is the usual way scenarios similar to Browse Categories are implemented.
 357  
              * 
 358  
              *         [The old way was a loCatRpcServiceAsync call that returned LoCategoryInfos on success;
 359  
              *                         the loCategoryInfos did not have necessary CategoryType name info,
 360  
              *                                 and loCategories cannot be changed without affecting versioning 
 361  
              *                                 (which does not seem worth it given this present fix with searchDispatcherAsync).
 362  
              *                         Furthermore the old way was not the usual way scenarios similar to Browse Categories are implemented.]
 363  
              * 
 364  
              * KSLAB-2091         
 365  
              */
 366  0
             searchDispatcherAsync.search(new SearchRequest("lo.search.loCategories"), new KSAsyncCallback<SearchResult>() {
 367  
             @Override
 368  
             public void handleFailure(Throwable caught) {
 369  0
                 GWT.log("lo.search.loCategories failed", caught);
 370  0
                 Window.alert("lo.search.loCategories failed");
 371  0
                 callback.exec(false);
 372  0
             }
 373  
 
 374  
                         @Override
 375  
                         public void onSuccess(SearchResult results) {
 376  0
                                 loadTable(results);
 377  0
                 callback.exec(true);
 378  0
                 table.displayLoading(false);
 379  0
                         }
 380  
         });
 381  
             //KSLAB-2091
 382  0
     }
 383  
     
 384  
     private void loadTable(SearchResult results) {        /*Additional overload of loadTableto accommodate call from new loadTable(final Callback<Boolean> callback), 
 385  
                                                                                                                                                                                                                             which is directly above [KSLAB-2091]*/
 386  
             
 387  0
         resultRows.clear();
 388  
         
 389  0
         HashSet<String> hashSet = new HashSet<String>();
 390  0
         String curCatID = null, curCatNAME= null, curCatTYPEID= null, curCatTYPENAME= null, curCatSTATE=null;
 391  0
         String curSearchResultCellKEY= null;
 392  
         
 393  0
         for(SearchResultRow curSearchResultRow: results.getRows()) {
 394  0
                 for(SearchResultCell curSearchResultCell: curSearchResultRow.getCells()){        //Extracts necessary fields that will be added to resultRow below.
 395  0
                         curSearchResultCellKEY= curSearchResultCell.getKey();
 396  0
                         if(curSearchResultCellKEY.equals("lo.resultColumn.categoryId")){
 397  0
                                 curCatID= curSearchResultCell.getValue();
 398  0
                         }else if(curSearchResultCellKEY.equals("lo.resultColumn.categoryName")){
 399  0
                                 curCatNAME= curSearchResultCell.getValue();
 400  0
                         }else if(curSearchResultCellKEY.equals("lo.resultColumn.categoryType")){
 401  0
                                 curCatTYPEID= curSearchResultCell.getValue();
 402  0
                         }else if(curSearchResultCellKEY.equals("lo.resultColumn.categoryTypeName")){
 403  0
                             curCatTYPENAME= curSearchResultCell.getValue();
 404  0
                 }else if(curSearchResultCellKEY.equals("lo.resultColumn.categoryState")){        //From new bean in lo-search-config.xml
 405  0
                                 curCatSTATE= curSearchResultCell.getValue();
 406  
                 }
 407  
                 }
 408  
                 
 409  0
             if (isHideInactiveCategories() && curCatSTATE.equalsIgnoreCase("inactive")) {
 410  0
                 continue;
 411  
             }
 412  
 
 413  0
             ResultRow resultRow = new ResultRow();
 414  
             
 415  0
             if (!hashSet.contains(curCatID)) {
 416  0
                 hashSet.add(curCatID);
 417  0
                 resultRow.setValue(ID_COLUMN_KEY, curCatID);
 418  0
                 resultRow.setValue(NAME_COLUMN_KEY, curCatNAME);
 419  0
                 resultRow.setValue(TYPE_COLUMN_KEY, curCatTYPEID);
 420  0
                 resultRow.setValue(TYPE_NAME_COLUMN_KEY, curCatTYPENAME);
 421  0
                 resultRow.setValue(STATE_COLUMN_KEY, curCatSTATE);
 422  0
                 resultRows.add(resultRow);                
 423  
             }
 424  0
         }        //Correct resultRows now loaded [KSLAB-2091]
 425  0
         redraw();
 426  0
     }
 427  
 
 428  
     public List<ResultRow> getRowsByType(String type){
 429  0
         List<ResultRow> bufferList = new ArrayList<ResultRow>();
 430  0
         for(ResultRow row : resultRows) {
 431  0
             if(row.getValue(TYPE_COLUMN_KEY).contains(type)){
 432  0
                 bufferList.add(row);
 433  
             }
 434  
         }
 435  0
         return bufferList;
 436  
     }
 437  
     
 438  
     public List<ResultRow> getRowsLikeName(String name){
 439  0
         List<ResultRow> bufferList = new ArrayList<ResultRow>();
 440  0
         for(ResultRow row : resultRows) {
 441  0
             String nameValue = row.getValue(NAME_COLUMN_KEY);
 442  0
             if(nameValue != null) {
 443  0
                 String[] words = nameValue.split("\\W");
 444  0
                 for(String word : words){
 445  0
                     if(word.toUpperCase().startsWith(name.toUpperCase())){
 446  0
                         bufferList.add(row);
 447  0
                         break;
 448  
                     }                    
 449  
                 }
 450  
             }
 451  0
         }
 452  0
         return bufferList;
 453  
     }
 454  
 }