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