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