Coverage Report - org.kuali.student.common.ui.client.widgets.suggestbox.SearchSuggestOracle
 
Classes in this File Line Coverage Branch Coverage Complexity
SearchSuggestOracle
0%
0/102
0%
0/34
2.895
SearchSuggestOracle$1
0%
0/11
0%
0/4
2.895
SearchSuggestOracle$2
0%
0/3
N/A
2.895
SearchSuggestOracle$3
0%
0/43
0%
0/24
2.895
SearchSuggestOracle$4
0%
0/17
0%
0/10
2.895
 
 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.common.ui.client.widgets.suggestbox;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.List;
 20  
 
 21  
 import org.kuali.student.common.assembly.data.LookupMetadata;
 22  
 import org.kuali.student.common.assembly.data.LookupParamMetadata;
 23  
 import org.kuali.student.common.assembly.data.Metadata.WriteAccess;
 24  
 import org.kuali.student.common.search.dto.SearchParam;
 25  
 import org.kuali.student.common.search.dto.SearchRequest;
 26  
 import org.kuali.student.common.search.dto.SearchResult;
 27  
 import org.kuali.student.common.search.dto.SearchResultCell;
 28  
 import org.kuali.student.common.search.dto.SearchResultRow;
 29  
 import org.kuali.student.common.search.dto.SortDirection;
 30  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 31  
 import org.kuali.student.common.ui.client.service.CachingSearchService;
 32  
 import org.kuali.student.common.ui.client.service.SearchRpcServiceAsync;
 33  
 import org.kuali.student.common.ui.client.service.SearchServiceFactory;
 34  
 import org.kuali.student.common.ui.client.widgets.KSErrorDialog;
 35  
 import org.kuali.student.common.ui.client.widgets.notification.LoadingDiv;
 36  
 
 37  
 import com.google.gwt.user.client.ui.HasText;
 38  
 import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
 39  
 import com.google.gwt.user.client.ui.Widget;
 40  
 
 41  0
 public class SearchSuggestOracle extends IdableSuggestOracle{
 42  
     
 43  
     private String searchTypeKey;
 44  
     private String searchIdKey;
 45  
     private String searchTextKey;
 46  
     private String resultIdKey;
 47  
     private Callback currentCallback;
 48  
     private Request pendingRequest;
 49  
     private Callback pendingCallback;
 50  
     private HasText textWidget;
 51  
     private String resultDisplayKey;
 52  
     private String resultSortKey;
 53  
     private SortDirection sortDirection;
 54  0
     private List<SearchParam> additionalParams = new ArrayList<SearchParam>();
 55  0
     private List<IdableSuggestion> lastSuggestions = new ArrayList<IdableSuggestion>();
 56  
     
 57  
     private LookupMetadata lookupMetaData;
 58  0
     private CachingSearchService cachingSearchService = CachingSearchService.getSearchService();
 59  0
     private SearchRpcServiceAsync searchService = SearchServiceFactory.getSearchService();
 60  
 
 61  0
     private List<org.kuali.student.common.ui.client.mvc.Callback<IdableSuggestion>> searchCompletedCallbacks = new ArrayList<org.kuali.student.common.ui.client.mvc.Callback<IdableSuggestion>>();
 62  
     
 63  0
     private LoadingDiv loading = new LoadingDiv();
 64  
     
 65  
     /**
 66  
      * @deprecated
 67  
      * @param searchTypeKey the type to be search on
 68  
      * @param searchTextKey the column/key that to search on
 69  
      * @param idKey the column/key that is the primary key for this type
 70  
      */
 71  0
     public SearchSuggestOracle(String searchTypeKey, String searchTextKey, String searchIdKey, String resultIdKey, String resultDisplayKey){
 72  0
         this.searchTypeKey = searchTypeKey;
 73  0
         this.searchTextKey = searchTextKey;
 74  0
         this.searchIdKey = searchIdKey;
 75  0
         this.resultIdKey = resultIdKey;
 76  0
         this.resultDisplayKey = resultDisplayKey;
 77  0
     }
 78  
     
 79  
     /*
 80  
      * 
 81  
      */
 82  0
     public SearchSuggestOracle(LookupMetadata lookupMetadata) {
 83  0
             this.lookupMetaData = lookupMetadata;
 84  0
         this.searchTypeKey = lookupMetaData.getSearchTypeId();
 85  
         
 86  0
         for (LookupParamMetadata param : lookupMetadata.getParams()) {
 87  0
                 if ((param.getUsage() != null) && param.getUsage().name().equals("DEFAULT")) {
 88  0
                         this.searchTextKey = param.getKey();
 89  
                 }
 90  
                 //Add in any writeaccess never default values to the additional params
 91  0
                 if(WriteAccess.NEVER.equals(param.getWriteAccess())||param.getDefaultValueString()!=null||param.getDefaultValueList()!=null){
 92  0
                         SearchParam searchParam = new SearchParam();
 93  0
                         searchParam.setKey(param.getKey());
 94  0
                                 if(param.getDefaultValueList()==null){
 95  0
                                         searchParam.setValue(param.getDefaultValueString());
 96  
                                 }else{
 97  0
                                         searchParam.setValue(param.getDefaultValueList());
 98  
                                 }
 99  0
                         additionalParams.add(searchParam);
 100  0
                 }
 101  
         }
 102  0
         if (this.searchTextKey == null) {
 103  0
                 KSErrorDialog.show(new Throwable("Cannot find searchTextKey for " + searchTypeKey) );
 104  
         }
 105  
         
 106  0
         this.searchIdKey = lookupMetadata.getSearchParamIdKey();
 107  0
         this.resultIdKey = lookupMetadata.getResultReturnKey();
 108  0
         this.resultDisplayKey = lookupMetadata.getResultDisplayKey();
 109  0
         this.resultSortKey = lookupMetadata.getResultSortKey();
 110  0
         this.sortDirection = lookupMetadata.getSortDirection();
 111  0
     }
 112  
 
 113  
     public void setAdditionalSearchParams(List<SearchParam> params){
 114  0
         additionalParams = params;
 115  0
     }
 116  
     
 117  0
     private Callback wrappedCallback = new Callback() {
 118  
 
 119  
         public void onSuggestionsReady(Request request, Response response) {
 120  0
           if (textWidget.getText().equals(request.getQuery())) {
 121  0
             currentCallback.onSuggestionsReady(request, response);
 122  0
             pendingRequest = null;
 123  0
             pendingCallback = null;
 124  
           }
 125  0
           currentCallback = null;
 126  0
           if (pendingCallback != null) {
 127  0
             requestSuggestions(pendingRequest, pendingCallback);
 128  0
             pendingRequest = null;
 129  0
             pendingCallback = null;
 130  
           }
 131  0
         }
 132  
 
 133  
     };
 134  
     
 135  
     @Override
 136  
     public void requestSuggestions(Request request, Callback callback) {
 137  
         // Check if the request query is smaller than the minimum size allowed
 138  0
         String query = request.getQuery().trim();
 139  0
         int minQuerySize = 0;
 140  
         
 141  
         //[KSCOR-225] LO's currently use the depricated constructor that does not pass in the 
 142  
         // lookupMetaData so we need to do a null check until that is fixed
 143  0
         if (lookupMetaData != null && lookupMetaData.getMinQuerySize() != null){
 144  0
             minQuerySize = lookupMetaData.getMinQuerySize().intValue();
 145  
         }
 146  0
         if ((currentCallback == null) && (query.length() >= minQuerySize)){
 147  0
           final int x = ((Widget)this.textWidget).getAbsoluteLeft() + ((Widget)this.textWidget).getOffsetWidth();
 148  0
                     final int y = ((Widget)this.textWidget).getAbsoluteTop() + ((Widget)this.textWidget).getOffsetHeight();
 149  0
                     loading.setPopupPositionAndShow(new PositionCallback(){
 150  
 
 151  
                                   @Override
 152  
                                   public void setPosition(int offsetWidth, int offsetHeight) {
 153  0
                                           loading.setPopupPosition(x - offsetWidth, y + 1);
 154  0
                                   }
 155  
                           });
 156  0
           currentCallback = callback;
 157  0
           sendRequest(request, wrappedCallback);
 158  0
         } else {
 159  0
           pendingRequest = request;
 160  0
           pendingCallback = callback;
 161  
         }        
 162  0
     }
 163  
     
 164  
     private SearchRequest buildSearchRequest(String query, String searchId) {
 165  0
             SearchRequest sr = new SearchRequest();
 166  0
             sr.setNeededTotalResults(false);
 167  0
             sr.setSearchKey(this.searchTypeKey);
 168  0
             sr.setSortColumn(this.resultSortKey);
 169  0
         sr.setSortDirection(this.sortDirection);
 170  
 
 171  0
                 List<SearchParam> searchParams = new ArrayList<SearchParam>();
 172  0
                 SearchParam param1 = createParam(this.searchTextKey, query);
 173  0
                 searchParams.add(param1);
 174  
                 
 175  0
             sr.setParams(searchParams);
 176  
             
 177  0
             sr.getParams().addAll(additionalParams);
 178  
 
 179  0
         return sr;
 180  
     }
 181  
     
 182  
     private SearchRequest buildSearchRequestById(String query, String searchId) {
 183  0
             SearchRequest sr = new SearchRequest();
 184  0
             sr.setNeededTotalResults(false);
 185  0
             sr.setSearchKey(this.searchTypeKey);
 186  0
             sr.setSortColumn(this.resultSortKey);
 187  0
         sr.setSortDirection(this.sortDirection);
 188  
 
 189  0
                 List<SearchParam> searchParams = new ArrayList<SearchParam>();
 190  0
                 SearchParam param2 = createParam(this.searchIdKey, searchId);
 191  0
                 searchParams.add(param2);
 192  
                 
 193  0
             sr.setParams(searchParams);
 194  
             
 195  0
             sr.getParams().addAll(additionalParams);
 196  
 
 197  0
         return sr;
 198  
     }
 199  
     
 200  
     private SearchParam createParam(String key, String value) {
 201  0
             SearchParam param = new SearchParam();
 202  
             
 203  0
             if(key == null) {
 204  0
                         param.setKey("");
 205  
                 } else {
 206  0
                         param.setKey(key);
 207  
                 }
 208  
 
 209  0
             if(value == null) {
 210  0
                         param.setValue("");
 211  
                 } else {
 212  0
                         param.setValue(value);
 213  
                 }
 214  
             
 215  0
             return param;
 216  
     }
 217  
 
 218  
     public void sendRequest(final Request request, final Callback callback){
 219  0
         String query = request.getQuery().trim();
 220  0
         SearchRequest searchRequest = buildSearchRequest(query, null);
 221  
         
 222  
         //case-sensitive?
 223  0
         if(query.length() > 0){
 224  0
                 searchService.search(searchRequest, new KSAsyncCallback<SearchResult>(){
 225  
     
 226  
                 @Override
 227  
                 public void onSuccess(SearchResult results) {
 228  0
                     lastSuggestions = createSuggestions(results, request.getLimit());
 229  0
                     Response response = new Response(lastSuggestions);
 230  0
                     loading.hide();
 231  0
                     callback.onSuggestionsReady(request, response);
 232  0
                     if (searchCompletedCallbacks != null &&
 233  
                             lastSuggestions != null && lastSuggestions.size() == 1) {
 234  0
                         for (org.kuali.student.common.ui.client.mvc.Callback<IdableSuggestion> callback : searchCompletedCallbacks) {
 235  0
                             callback.exec(lastSuggestions.get(0));
 236  
                         }
 237  
                     }
 238  0
                 }
 239  
                 
 240  
                 @Override
 241  
                 public void onFailure(Throwable caught) {
 242  0
                         loading.hide();
 243  0
                         super.onFailure(caught);
 244  0
                 }
 245  
                 
 246  
                 private List<IdableSuggestion> createSuggestions(SearchResult results, int limit){
 247  0
                     List<IdableSuggestion> suggestionsList = new ArrayList<IdableSuggestion>();
 248  0
                     String query = request.getQuery();
 249  0
                     query = query.trim();
 250  0
                     int count = 0;
 251  0
                     if(results != null){
 252  0
                         for (SearchResultRow r: results.getRows()){
 253  0
                             if(count == limit){
 254  0
                                 break;
 255  
                             }
 256  
 
 257  0
                             IdableSuggestion theSuggestion = new IdableSuggestion();
 258  0
                             for(SearchResultCell c: r.getCells()){
 259  0
                                 if(c.getKey().equals(resultDisplayKey)){
 260  0
                                     String itemText = c.getValue();
 261  0
                                     theSuggestion.addAttr(c.getKey(), c.getValue());
 262  0
                                     int index = (" " + itemText).toLowerCase().indexOf(" " + query.toLowerCase().trim());
 263  
                                     
 264  0
                                     if (index < 0) {
 265  
                                         //temporary fix to stop index out of bound exception in hosted mode
 266  
 //                                        continue;
 267  
                                         //Including fuzzy search results in the display list.
 268  0
                                         theSuggestion.setDisplayString(itemText);
 269  0
                                         theSuggestion.setReplacementString(itemText);
 270  
                                             //FIXME handle case when search for text is not appearing within search result - should not happen (misconfiguration)
 271  0
                                         continue;
 272  
                                     }
 273  
                                     
 274  0
                                     String htmlString = itemText.substring(0,index) + "<b>" + itemText.substring(index, index + query.length()) + "</b>" + itemText.substring(index + query.length(), itemText.length());
 275  0
                                     theSuggestion.setDisplayString(htmlString);
 276  0
                                     theSuggestion.setReplacementString(itemText);
 277  0
                                     if (c.getKey().equals(resultIdKey)){
 278  0
                                         theSuggestion.setId(c.getValue());
 279  
                                     }
 280  0
                                 } else if(c.getKey().equals(resultIdKey)){
 281  0
                                      theSuggestion.setId(c.getValue());
 282  0
                                      theSuggestion.addAttr(c.getKey(), c.getValue());
 283  
                                 } else{
 284  0
                                     theSuggestion.addAttr(c.getKey(), c.getValue());
 285  
                                 }
 286  
                             }
 287  0
                             suggestionsList.add(theSuggestion);
 288  0
                             count++;
 289  0
                         }
 290  
                     }
 291  0
                     return suggestionsList;
 292  
                 }
 293  
             });
 294  
         }
 295  0
     }
 296  
 
 297  
     @Override
 298  
     public boolean isDisplayStringHTML() {
 299  0
         return true;
 300  
     }
 301  
 
 302  
 /*    
 303  
     public IdableSuggestion getSuggestionById(String id) {
 304  
         IdableSuggestion suggestion = null;
 305  
         if(!(lastSuggestions.isEmpty())){
 306  
             for(IdableSuggestion is: lastSuggestions){
 307  
                 if(is.getId().equals(id)){
 308  
                     suggestion = is;
 309  
                     break;
 310  
                 }
 311  
             }
 312  
         }
 313  
         if(suggestion == null){
 314  
             searchOnId(id);
 315  
         }
 316  
         return suggestion;
 317  
     }*/
 318  
 
 319  
     @Override
 320  
     public IdableSuggestion getSuggestionByText(String text){
 321  0
         IdableSuggestion suggestion = null;
 322  0
         for(IdableSuggestion is: lastSuggestions){
 323  0
             if(is.getReplacementString().trim().equalsIgnoreCase(text.trim())){
 324  0
                 suggestion = is;
 325  0
                 break;
 326  
             }
 327  
         }
 328  0
         return suggestion;
 329  
     }
 330  
     
 331  
     public void setTextWidget(HasText widget){
 332  0
         textWidget = widget;
 333  0
     }
 334  
 
 335  
     @Override
 336  
     public void getSuggestionByIdSearch(String id, final org.kuali.student.common.ui.client.mvc.Callback<IdableSuggestion> callback) {
 337  0
         SearchRequest searchRequest = buildSearchRequestById(null, id);
 338  0
         cachingSearchService.search(searchRequest, new KSAsyncCallback<SearchResult>(){
 339  
             @Override
 340  
             public void onSuccess(SearchResult results) {
 341  0
                 IdableSuggestion theSuggestion = null;
 342  0
                 if(results != null && !results.getRows().isEmpty()){
 343  0
                         SearchResultRow r = results.getRows().get(0);
 344  0
                     theSuggestion = new IdableSuggestion();
 345  0
                     for(SearchResultCell c: r.getCells()){
 346  0
                         if(c.getKey().equals(resultDisplayKey)){
 347  0
                             String itemText = c.getValue();
 348  0
                             theSuggestion.addAttr(c.getKey(), c.getValue());
 349  0
                             theSuggestion.setDisplayString(itemText);
 350  0
                             theSuggestion.setReplacementString(itemText);
 351  0
                         } else if(c.getKey().equals(resultIdKey)){
 352  0
                              theSuggestion.setId(c.getValue());
 353  0
                              theSuggestion.addAttr(c.getKey(), c.getValue());
 354  
                         } else {
 355  0
                             theSuggestion.addAttr(c.getKey(), c.getValue());
 356  
                         }
 357  
                     }
 358  
                 }
 359  0
                 callback.exec(theSuggestion);
 360  0
             }
 361  
         });
 362  0
     }
 363  
 
 364  
     @Override
 365  
     public void addSearchCompletedCallback(org.kuali.student.common.ui.client.mvc.Callback<IdableSuggestion> callback) {
 366  0
         searchCompletedCallbacks.add(callback);
 367  0
     }
 368  
     
 369  
 }