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