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