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