001/** 002 * Copyright 2010 The Kuali Foundation Licensed under the 003 * Educational Community License, Version 2.0 (the "License"); you may 004 * not use this file except in compliance with the License. You may 005 * obtain a copy of the License at 006 * 007 * http://www.osedu.org/licenses/ECL-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, 010 * software distributed under the License is distributed on an "AS IS" 011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 012 * or implied. See the License for the specific language governing 013 * permissions and limitations under the License. 014 */ 015 016package org.kuali.student.common.ui.client.widgets.search; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.kuali.student.common.ui.client.application.Application; 025import org.kuali.student.common.ui.client.configurable.mvc.DefaultWidgetFactory; 026import org.kuali.student.common.ui.client.mvc.Callback; 027import org.kuali.student.common.ui.client.util.UtilConstants; 028import org.kuali.student.common.ui.client.widgets.KSButton; 029import org.kuali.student.common.ui.client.widgets.KSDropDown; 030import org.kuali.student.common.ui.client.widgets.KSLabel; 031import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle; 032import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations; 033import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.ButtonEnum; 034import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup; 035import org.kuali.student.common.ui.client.widgets.field.layout.button.ButtonGroup; 036import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement; 037import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayoutComponent; 038import org.kuali.student.common.ui.client.widgets.layout.HorizontalBlockFlowPanel; 039import org.kuali.student.common.ui.client.widgets.layout.VerticalFlowPanel; 040import org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract; 041import org.kuali.student.common.ui.client.widgets.list.ListItems; 042import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent; 043import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler; 044import org.kuali.student.common.ui.client.widgets.searchtable.ResultRow; 045import org.kuali.student.r1.common.assembly.data.LookupMetadata; 046import org.kuali.student.r1.common.assembly.data.LookupMetadata.Usage; 047import org.kuali.student.r1.common.assembly.data.LookupParamMetadata; 048import org.kuali.student.r1.common.assembly.data.Metadata; 049import org.kuali.student.r1.common.assembly.data.Metadata.WriteAccess; 050import org.kuali.student.r2.core.search.dto.SearchParamInfo; 051import org.kuali.student.r2.core.search.dto.SearchRequestInfo; 052 053import com.google.gwt.core.client.GWT; 054import com.google.gwt.event.dom.client.ClickEvent; 055import com.google.gwt.event.dom.client.ClickHandler; 056import com.google.gwt.event.dom.client.KeyCodes; 057import com.google.gwt.event.dom.client.KeyDownEvent; 058import com.google.gwt.event.dom.client.KeyDownHandler; 059import com.google.gwt.event.shared.HandlerRegistration; 060import com.google.gwt.user.client.Window; 061import com.google.gwt.user.client.ui.Composite; 062import com.google.gwt.user.client.ui.HTMLPanel; 063import com.google.gwt.user.client.ui.HasText; 064import com.google.gwt.user.client.ui.HasValue; 065import com.google.gwt.user.client.ui.SimplePanel; 066import com.google.gwt.user.client.ui.SuggestBox; 067import com.google.gwt.user.client.ui.VerticalPanel; 068import com.google.gwt.user.client.ui.Widget; 069 070public class SearchPanel extends Composite{ 071 072 //Layout configuration 073 private VerticalFlowPanel layout = new VerticalFlowPanel(); 074 private SimplePanel searchSelectorPanel = new SimplePanel(); 075 private VerticalFlowPanel resultsTablePanel = new VerticalFlowPanel(); 076 private HorizontalBlockFlowPanel enteredCriteriaString = new HorizontalBlockFlowPanel(); 077 private CollapsablePanel modifySearchPanel; 078 private String criteriaInstructions = getMessage("searchPanelEnterFields"); 079 private KSLabel enteredCriteriaHeading = new KSLabel(getMessage("searchPanelCriteria")); 080 protected SearchResultsTable table; 081 private boolean isMultiSelect = true; 082 083 public static enum SearchStyle{ADVANCED, CUSTOM}; 084 private ActionCancelGroup actionCancelButtons; 085 086 private String actionLabel = getMessage("search"); //set default action label 087 private boolean resultsSelected = false; 088 private boolean hasSearchParams = false; //indicates if there are any user supplied search parameters 089 //if false will auto default search and not display modify search link. 090 091 //Search data 092 private List<LookupMetadata> lookups = new ArrayList<LookupMetadata>(); 093 private boolean multiSelect = false; 094 private boolean resultsShown = false; 095 private SearchParametersWidget activeSearchParametersWidget = null; 096 // uses "name" of the lookup metadata to lookup the widget that layouts the search UI 097 private Map<String, SearchParametersWidget> searchParameterWidgetMap = new HashMap<String, SearchParametersWidget>(); 098 private List<SearchField> searchFields = new ArrayList<SearchField>(); 099 private List<Callback<LookupMetadata>> lookupChangedCallbacks = new ArrayList<Callback<LookupMetadata>>(); 100 private String selectedLookupName; 101 private List<Callback<List<SelectedResults>>> selectedCompleteCallbacks = new ArrayList<Callback<List<SelectedResults>>>(); 102 private List<Callback<Boolean>> actionCompletedCallbacks = new ArrayList<Callback<Boolean>>(); 103 104 private Callback<ButtonEnumerations.ButtonEnum> actionCancelCallback = new Callback<ButtonEnumerations.ButtonEnum>(){ 105 106 @Override 107 public void exec(ButtonEnum result) { 108 if (result == ButtonEnumerations.SearchCancelEnum.SEARCH) { 109 table.removeContent(); 110 getActionCompleteCallback().exec(true); 111 } 112 } 113 }; 114 115 interface SearchParametersWidget { 116 public SearchRequestInfo getSearchRequest(); 117 public LookupMetadata getLookupMetadata(); 118 public List<HasSearchParam> getSearchParams(); 119 } 120 121 public SearchPanel(LookupMetadata meta){ 122 lookups.add(meta); 123 this.initWidget(layout); 124 } 125 126 public SearchPanel(List<LookupMetadata> metas){ 127 lookups = metas; 128 this.initWidget(layout); 129 } 130 131 @SuppressWarnings("unchecked") 132 public ButtonGroup getButtons(){ 133 return actionCancelButtons; 134 } 135 136 public void setMutipleSelect(boolean isMultiSelect){ 137 this.isMultiSelect = isMultiSelect; 138 } 139 140 public void setupButtons() { 141 if (actionCancelButtons != null) { 142 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 143 actionCancelButtons.addCallback(actionCancelCallback); 144 } 145 } 146 147 public void setupSearch() { 148 resultsTablePanel.clear(); 149 layout.clear(); 150 resultsShown = false; 151 hasSearchParams = false; 152 int firstLookUpValue = 0; 153 154 //create search panel 155 Widget searchParamPanel; 156 if (lookups.size() == 1) { 157 searchParamPanel = createSearchParamPanel(lookups.get(firstLookUpValue)); 158 selectedLookupName = lookups.get(firstLookUpValue).getName(); 159 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookupName); 160 } else { 161 LinkedHashMap<String, Widget> searches = new LinkedHashMap<String, Widget>(); 162 LinkedHashMap<String, LookupMetadata> searchLookups = new LinkedHashMap<String, LookupMetadata>(); 163 for(LookupMetadata lookup: lookups){ 164 searches.put(lookup.getName(), createSearchParamPanel(lookup)); 165 searchLookups.put(lookup.getName(), lookup); 166 } 167 selectedLookupName = lookups.get(firstLookUpValue).getName(); 168 // Sets the activeSearchParametersWidget to be the first search 169 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookupName); 170 String actionLabel = (lookups.get(firstLookUpValue) == null)? null : lookups.get(firstLookUpValue) 171 .getWidgetOptionValue(LookupMetadata.WidgetOption.ADVANCED_LIGHTBOX_ACTION_LABEL); 172 setActionLabel(actionLabel); 173 searchParamPanel = new SwappablePanel(searches); 174 ((SwappablePanel)searchParamPanel).setSearchLookups(searchLookups); 175 ((SwappablePanel)searchParamPanel).addLookupChangedCallback(new Callback<LookupMetadata>() { 176 @Override 177 public void exec(LookupMetadata selectedLookup) { 178 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookup.getName()); 179 selectedLookupName = selectedLookup.getName(); 180 if (lookupChangedCallbacks != null) { 181 for (Callback<LookupMetadata> callback : lookupChangedCallbacks) { 182 callback.exec(selectedLookup); 183 } 184 } 185 } 186 }); 187 } 188 searchSelectorPanel.setWidget(searchParamPanel); 189 layout.add(searchSelectorPanel); 190 191 //Create layout for results screen 192 193 //Entered criteria section 194 if (hasSearchParams){ 195 enteredCriteriaHeading.addStyleName("ks-form-module-single-line-margin"); 196 enteredCriteriaHeading.addStyleName("KS-Advanced-Search-Search-Criteria-Label"); 197 resultsTablePanel.add(enteredCriteriaHeading); 198 resultsTablePanel.add(enteredCriteriaString); 199 resultsTablePanel.setVisible(false); 200 } 201 202 //Search Results table 203 table = GWT.create(SearchResultsTable.class); 204 table.setMutipleSelect(isMultiSelect); 205 table.addStyleName("KS-Advanced-Search-Results-Table"); 206 for (Callback<List<SelectedResults>> selectionCompleteCallback : selectedCompleteCallbacks) { 207 table.addSelectionCompleteCallback(selectionCompleteCallback); 208 } 209 resultsTablePanel.add(table); 210 layout.add(resultsTablePanel); 211 212 table.getMslabel().addClickHandler(new ClickHandler(){ 213 214 @Override 215 public void onClick(ClickEvent event) { 216 if(modifySearchPanel.isOpen()){ 217 modifySearchPanel.close(); 218 } 219 else{ 220 modifySearchPanel.open(); 221 } 222 223 resultsTablePanel.setVisible(false); 224 resultsSelected = false; 225 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 226 } 227 }); 228 229 resultsSelected = false; 230 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 231 232 //Execute the search and display the results of there are no user supplied search parameters defined 233 if (!hasSearchParams){ 234 getActionCompleteCallback().exec(true); 235 } 236 } 237 238 private Widget createSearchParamPanel(LookupMetadata meta){ 239 ParamListItems listItems = new ParamListItems(meta); 240 final AdvancedSearch advancedSearch = new AdvancedSearch(meta); 241 LinkPanel panel = new LinkPanel(SearchStyle.ADVANCED, advancedSearch); 242 searchParameterWidgetMap.put(meta.getName(), advancedSearch); 243 244 //check whether we need custom tab i.e. whether we have at least one parameter that should appear on custom tab 245 for(LookupParamMetadata metaParam: meta.getParams()){ 246 if (metaParam.getUsage() != null && metaParam.getUsage() != Usage.DEFAULT){ 247 hasSearchParams = true; //Only set to true if this only has user supplied params (i.e. params without default values) 248 } 249 if ((metaParam.getUsage() == Usage.CUSTOM) || (metaParam.getUsage() == Usage.ADVANCED_CUSTOM)) { 250 251 final CustomizedSearch customizedSearch = new CustomizedSearch(meta, listItems); 252 KSButton button = panel.addLinkToPanel(SearchStyle.ADVANCED, getMessage("searchPanelCustomizeSearch"), SearchStyle.CUSTOM); 253 button.addClickHandler(new ClickHandler(){ 254 255 @Override 256 public void onClick(ClickEvent event) { 257 resultsTablePanel.setVisible(false); 258 activeSearchParametersWidget = customizedSearch; 259 }}); 260 button.addStyleName("KS-Advanced-Search-Link"); 261 button.getParent().addStyleName("clearfix"); 262 panel.addPanel(SearchStyle.CUSTOM, customizedSearch); 263 button = panel.addLinkToPanel(SearchStyle.CUSTOM, getMessage("searchPanelReturnToAdvancedSearch"), SearchStyle.ADVANCED); 264 button.addClickHandler(new ClickHandler(){ 265 266 @Override 267 public void onClick(ClickEvent event) { 268 resultsTablePanel.setVisible(false); 269 activeSearchParametersWidget = advancedSearch; 270 }}); 271 button.addStyleName("KS-Advanced-Search-Link"); 272 button.getParent().addStyleName("clearfix"); 273 break; 274 } 275 } 276 277 return panel; 278 } 279 280 private class CustomizedSearch extends Composite implements SearchParametersWidget { 281 282 private List<CustomLine> lines = new ArrayList<CustomLine>(); 283 private List<HasSearchParam> searchParams = new ArrayList<HasSearchParam>(); 284 private VerticalPanel layout = new VerticalPanel(); 285 private VerticalPanel linePanel = new VerticalPanel(); 286 private LookupMetadata meta; 287 288 public CustomizedSearch(final LookupMetadata meta, final ParamListItems listItems){ 289 290 KSLabel instrLabel = new KSLabel(criteriaInstructions); 291 layout.add(instrLabel); 292 293 layout.add(linePanel); 294 CustomLine line = new CustomLine(meta, listItems); 295 line.addStyleName("ks-form-module-single-line-margin"); 296 linePanel.add(line); 297 lines.add(line); 298 searchParams.add(line); 299 this.meta = meta; 300 301 KSButton addCriteria = new KSButton(getMessage("searchPanelAddCriteria"), ButtonStyle.SECONDARY); 302 addCriteria.addClickHandler(new ClickHandler(){ 303 304 @Override 305 public void onClick(ClickEvent event) { 306 CustomLine line = new CustomLine(meta, listItems); 307 line.addStyleName("ks-form-module-single-line-margin"); 308 linePanel.add(line); 309 lines.add(line); 310 searchParams.add(line); 311 } 312 }); 313 314 addCriteria.addStyleName("ks-form-module-single-line-margin"); 315 layout.add(addCriteria); 316 317 this.initWidget(layout); 318 } 319 320 public LookupMetadata getLookupMetadata() { 321 return meta; 322 } 323 324 @Override 325 public SearchRequestInfo getSearchRequest() { 326 //Create search request and then pass it to the table 327 //TODO pass search to the table 328 SearchRequestInfo sr = new SearchRequestInfo(); 329 List<SearchParamInfo> params = new ArrayList<SearchParamInfo>(); 330 for(CustomLine field: lines){ 331 SearchParamInfo param = field.getSearchParam(); 332 //TODO is this check needed here? probably. assuming string here 333 if((param.getValues().get(0) != null)){ 334 params.add(param); 335 } 336 } 337 338 //add search criteria widgets to the custom tab 339 for(LookupParamMetadata metaParam: meta.getParams()){ 340 341 //select only parameters shown on custom search tab 342 if ((metaParam.getUsage() != Usage.CUSTOM) && (metaParam.getUsage() != Usage.ADVANCED_CUSTOM)) { 343 continue; 344 } 345 346 if(metaParam.getWriteAccess() == WriteAccess.NEVER){ 347 SearchParamInfo param = new SearchParamInfo(); 348 param.setKey(metaParam.getKey()); 349 if(metaParam.getDefaultValueList()==null){ 350 param.getValues().add(metaParam.getDefaultValueString()); 351 }else{ 352 param.setValues(metaParam.getDefaultValueList()); 353 } 354 params.add(param); 355 } 356 else if(metaParam.getWriteAccess() == WriteAccess.WHEN_NULL){ 357 if((metaParam.getDefaultValueString() != null && !metaParam.getDefaultValueString().isEmpty())|| 358 (metaParam.getDefaultValueList() != null && !metaParam.getDefaultValueList().isEmpty())){ 359 SearchParamInfo param = new SearchParamInfo(); 360 param.setKey(metaParam.getKey()); 361 if(metaParam.getDefaultValueList()==null){ 362 param.getValues().add(metaParam.getDefaultValueString()); 363 }else{ 364 param.setValues(metaParam.getDefaultValueList()); 365 } 366 params.add(param); 367 } 368 } 369 } 370 371 sr.setParams(params); 372 sr.setSearchKey(meta.getSearchTypeId()); 373 return sr; 374 } 375 376 @Override 377 public List<HasSearchParam> getSearchParams() { 378 return searchParams; 379 } 380 381 } 382 383 private interface HasSearchParam{ 384 public SearchParamInfo getSearchParam(); 385 public String getFieldName(); 386 public String getSearchText(); 387 } 388 389 private static class CustomLine extends Composite implements HasSearchParam{ 390 private KSDropDown paramSelector = new KSDropDown(); 391 private SimplePanel widgetPanel = new SimplePanel(); 392 private Widget widget = null; 393 private String key; 394 private HorizontalBlockFlowPanel layout = new HorizontalBlockFlowPanel(); 395 private ParamListItems listItems; 396 397 public CustomLine(LookupMetadata meta, final ParamListItems listItems){ 398 399 List<LookupParamMetadata> customParams = new ArrayList<LookupParamMetadata>(); 400 401 for (LookupParamMetadata lookupParamMetadata : listItems.getParams()) { 402 if (lookupParamMetadata.getWriteAccess() != WriteAccess.NEVER){ 403 if (lookupParamMetadata.getUsage() == Usage.CUSTOM || lookupParamMetadata.getUsage() == Usage.ADVANCED_CUSTOM ) { 404 customParams.add(lookupParamMetadata); 405 } 406 } 407 } 408 409 for(LookupParamMetadata param:customParams){ 410 String id = param.getKey()+"-name"; 411 if(Application.getApplicationContext().getMessage(id)!=null) 412 { 413 param.setName(Application.getApplicationContext().getMessage(id)); 414 } 415 } 416 417 ParamListItems customParamList = new ParamListItems(customParams); 418 419 this.listItems = customParamList; 420 paramSelector.setBlankFirstItem(false); 421 paramSelector.setListItems(customParamList); 422 423 String id = meta.getParams().get(0).getKey(); 424 paramSelector.selectItem(id); 425 widget = listItems.getWidget(id); 426 key = id; 427 widgetPanel.setWidget(widget); 428 paramSelector.addSelectionChangeHandler(new SelectionChangeHandler(){ 429 430 @Override 431 public void onSelectionChange(SelectionChangeEvent event) { 432 String id = ((KSSelectItemWidgetAbstract)event.getWidget()).getSelectedItem(); 433 widget = listItems.getWidget(id); 434 widgetPanel.setWidget(widget); 435 key = id; 436 437 } 438 }); 439 layout.add(paramSelector); 440 layout.add(widgetPanel); 441 this.initWidget(layout); 442 } 443 444 public SearchParamInfo getSearchParam(){ 445 return SearchPanel.getSearchParam(widget, key); 446 } 447 448 public String getKey(){ 449 return key; 450 } 451 452 public String getFieldName(){ 453 String id = paramSelector.getSelectedItem(); 454 return listItems.getItemText(id); 455 } 456 457 @Override 458 public String getSearchText() { 459 return SearchPanel.getSearchText(widget); 460 } 461 } 462 463 private class AdvancedSearch extends Composite implements SearchParametersWidget { 464 private LookupMetadata meta; 465 private List<HasSearchParam> searchParams = new ArrayList<HasSearchParam>(); 466 467 public AdvancedSearch(final LookupMetadata meta){ 468 VerticalPanel panel = new VerticalPanel(); 469 470 KSLabel instrLabel = new KSLabel(); 471 panel.add(instrLabel); 472 this.meta = meta; 473 String searchId = meta.getId(); 474 475 //add widget for each search criteria to the advanced tab 476 boolean allFieldsRequired = true; 477 for(LookupParamMetadata param: meta.getParams()){ 478 479 //select only parameters shown on advanced search tab 480 if ((param.getUsage() != Usage.ADVANCED) && (param.getUsage() != Usage.ADVANCED_CUSTOM)) { 481 continue; 482 } 483 484 if ((param.getWriteAccess() == WriteAccess.ALWAYS) || (param.getWriteAccess() == WriteAccess.REQUIRED)){ 485 SearchField paramField = new SearchField(param, searchId); 486 searchFields.add(paramField); 487 panel.add(paramField); 488 searchParams.add(paramField); 489 } 490 else if (param.getWriteAccess() == WriteAccess.WHEN_NULL){ 491 if(param.getDefaultValueString() == null && param.getDefaultValueList() == null){ 492 SearchField paramField = new SearchField(param, searchId); 493 searchFields.add(paramField); 494 panel.add(paramField); 495 searchParams.add(paramField); 496 } 497 } 498 499 if (param.getWriteAccess() != Metadata.WriteAccess.REQUIRED) { 500 allFieldsRequired = false; 501 } 502 } 503 504 //do not show criteria instructions if we have only one criteria field or in case all fields are required 505 if ((searchFields.size() > 1) || (allFieldsRequired == false)) { 506 instrLabel.setText(criteriaInstructions); 507 } 508 this.addKeyDownHandler(downHandler); 509 this.initWidget(panel); 510 } 511 512 public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { 513 return addDomHandler(handler, KeyDownEvent.getType()); 514 } 515 516 public LookupMetadata getLookupMetadata() { 517 return meta; 518 } 519 520 private KeyDownHandler downHandler = new KeyDownHandler(){ 521 522 @Override 523 public void onKeyDown(KeyDownEvent event) { 524 if(event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) // Enter button 525 actionCancelCallback.exec(ButtonEnumerations.SearchCancelEnum.SEARCH); 526 } 527 528 }; 529 530 @Override 531 public SearchRequestInfo getSearchRequest() { 532 SearchRequestInfo sr = new SearchRequestInfo(); 533 List<SearchParamInfo> params = new ArrayList<SearchParamInfo>(); 534 List<HasSearchParam> searchParams = getSearchParams(); 535 536 //initialize search parameters if user entered values into search criteria fields in UI 537 538 for(HasSearchParam field: searchParams){ 539 SearchParamInfo param = field.getSearchParam(); 540 //TODO is this null check needed here? probably. assuming string here 541 //TODO make check more robust here/inserting params more robust 542 //do not pass to the search parameters that are empty 543 //FIXME hack - comparison to 'optional' - replace with check against 'optional' field and update related lookup metadata 544 if ((param.getValues().get(0) != null) && ((param.getValues().get(0).toString().trim().isEmpty() == false) || (param.getKey().toLowerCase().indexOf("optional") == -1))) { 545 params.add(param); 546 } 547 } 548 549 //initialize search parameters that are hidden from the UI because they are set to default context specific values 550 for(LookupParamMetadata metaParam: meta.getParams()){ 551 if(metaParam.getWriteAccess() == WriteAccess.NEVER){ 552 if ((metaParam.getDefaultValueString() == null || metaParam.getDefaultValueString().isEmpty())&& 553 (metaParam.getDefaultValueList() == null || metaParam.getDefaultValueList().isEmpty())) { 554 //FIXME throw an exception? 555 GWT.log("Key = " + metaParam.getKey() + " has write access NEVER but has no default value!", null); 556 continue; 557 } 558 SearchParamInfo param = new SearchParamInfo(); 559 param.setKey(metaParam.getKey()); 560 if(metaParam.getDefaultValueList()==null){ 561 param.getValues().add(metaParam.getDefaultValueString()); 562 }else{ 563 param.setValues(metaParam.getDefaultValueList()); 564 } 565 params.add(param); 566 } 567 else if(metaParam.getWriteAccess() == WriteAccess.WHEN_NULL){ 568 if((metaParam.getDefaultValueString() != null && !metaParam.getDefaultValueString().isEmpty())|| 569 (metaParam.getDefaultValueList() != null && !metaParam.getDefaultValueList().isEmpty())){ 570 SearchParamInfo param = new SearchParamInfo(); 571 param.setKey(metaParam.getKey()); 572 if(metaParam.getDefaultValueList()==null){ 573 param.getValues().add(metaParam.getDefaultValueString()); 574 }else{ 575 param.setValues(metaParam.getDefaultValueList()); 576 } 577 params.add(param); 578 } 579 } 580 } 581 sr.setParams(params); 582 if (meta.getResultSortKey() != null) { 583 sr.setSortColumn(meta.getResultSortKey()); 584 } 585 sr.setSearchKey(meta.getSearchTypeId()); 586 return sr; 587 } 588 589 @Override 590 public List<HasSearchParam> getSearchParams() { 591 return searchParams; 592 } 593 } 594 595 private class SearchField extends Composite implements HasSearchParam{ 596 597 private Widget widget = null; 598 private LookupParamMetadata meta = null; 599 private VerticalFlowPanel panel = new VerticalFlowPanel(); 600 private String fieldName; 601 602 public SearchParamInfo getSearchParam(){ 603 return SearchPanel.getSearchParam(widget, meta.getKey()); 604 } 605 606 public SearchField(LookupParamMetadata param, String searchId){ 607 meta = param; 608 //TODO use message call here 609 // KSCM-1326 This is where we implemented several options to override 610 // Search Field names. Loads custom overridden messages from KSMG_MESSAGE table. 611 if(getMessage(searchId + ":" + param.getKey()+ FieldLayoutComponent.NAME_MESSAGE_KEY)!=null) 612 fieldName = getMessage(searchId + ":" + param.getKey()+ FieldLayoutComponent.NAME_MESSAGE_KEY); 613 else if(getMessage(param.getKey()+FieldLayoutComponent.NAME_MESSAGE_KEY)!=null) 614 fieldName = getMessage(param.getKey()+FieldLayoutComponent.NAME_MESSAGE_KEY); 615 else 616 fieldName = param.getName(); 617 618 widget = DefaultWidgetFactory.getInstance().getWidget(param); 619 if(param.getDefaultValueString() != null){ 620 //TODO Add handling of default value lists here 621 if(widget instanceof HasText){ 622 ((HasText) widget).setText(param.getDefaultValueString().toString()); 623 } 624 else if(widget instanceof HasValue){ 625 ((HasValue) widget).setValue(param.getDefaultValueString()); 626 } 627 } 628 629 //FIXME: remove because required field '*' indication will be part of FieldElement class 630 if (param.getWriteAccess() == Metadata.WriteAccess.REQUIRED) { 631 fieldName += " *"; 632 } 633 634 FieldElement fieldElement = new FieldElement(fieldName, widget); 635 fieldElement.getTitleWidget().addStyleName("KS-Picker-Criteria-Text"); 636 panel.add(fieldElement); 637 panel.addStyleName("clearfix"); 638 639 this.initWidget(panel); 640 } 641 642 public Widget getFieldPanel(){ 643 return panel; 644 } 645 646 public String getFieldName() { 647 return fieldName; 648 } 649 650 @Override 651 public String getSearchText() { 652 return SearchPanel.getSearchText(widget); 653 } 654 } 655 656 private static SearchParamInfo getSearchParam(final Widget widget, String key){ 657 SearchParamInfo param = new SearchParamInfo(); 658 param.setKey(key); 659 if(widget instanceof HasText){ 660 param.getValues().add(((HasText) widget).getText()); 661 } 662 else if(widget instanceof HasValue){ 663 Object value = ((HasValue) widget).getValue(); 664 if(value != null){ 665 //TODO need to handle date and other types here, how they are converted for search, etc 666 if(value instanceof String){ 667 param.getValues().add((String)value); 668 } 669 else{ 670 param.getValues().add(value.toString()); 671 GWT.log("Fields in search probably(?) shouldnt have values other than string", null); 672 } 673 } 674 } 675 else if (widget instanceof KSPicker){ 676 KSPicker pickerWidget = (KSPicker)widget; 677 String pickerValue = pickerWidget.getValue().toString(); 678 if (UtilConstants.IMPOSSIBLE_CHARACTERS.equals(pickerValue)){ 679 SuggestBox suggestBox = (SuggestBox)pickerWidget.getInputWidget(); 680 pickerValue = suggestBox.getText(); 681 } 682 683 param.getValues().add(pickerValue); 684 } 685 else { 686 param.getValues().add(""); 687 } 688 689 return param; 690 } 691 692 private static String getSearchText(final Widget widget){ 693 if(widget instanceof HasText){ 694 return ((HasText) widget).getText(); 695 } 696 else if(widget instanceof HasValue){ 697 Object value = ((HasValue) widget).getValue(); 698 if(value != null){ 699 //TODO need to handle date and other types here, how they are converted for search, etc 700 if(value instanceof String){ 701 return (String)value; 702 } 703 else{ 704 GWT.log("Fields in search probably(?) shouldnt have values other than string", null); 705 return value.toString(); 706 } 707 } 708 } 709 else if (widget instanceof KSPicker){ 710 return ((KSPicker)widget).getDisplayValue(); 711 } 712 return ""; 713 } 714 715 private void showCriteriaChosen(List<HasSearchParam> fields){ 716 enteredCriteriaString.clear(); 717 boolean first = true;; 718 for(HasSearchParam field: fields){ 719 String name = field.getFieldName(); 720 String value = field.getSearchText(); 721 if(!value.isEmpty()&&value.equals("$$##@@")) 722 value = field.getSearchParam().getValues().get(0).toUpperCase(); 723 if(!value.isEmpty()){ 724 HTMLPanel label = new HTMLPanel(name + ": <b>" + value + "</b> "); 725 if (!first) { 726 label.addStyleName("KS-Advanced-Search-Search-Criteria-Text"); 727 } 728 enteredCriteriaString.add(label); 729 first = false; 730 } 731 } 732 } 733 734 public List<String> getSelectedIds(){ 735 List<String> ids = new ArrayList<String>(); 736 if(table != null){ 737 ids = table.getSelectedIds(); 738 } 739 return ids; 740 } 741 742 public List<SelectedResults> getSelectedValues() { 743 744 List<SelectedResults> selectedValues = new ArrayList<SelectedResults>(); 745 if (table != null) { 746 List<ResultRow> selectedRows = table.getSelectedRows(); 747 for (ResultRow row : selectedRows) { 748 String displayKey = row.getValue(activeSearchParametersWidget.getLookupMetadata().getResultDisplayKey()); 749 String returnKey = row.getValue(activeSearchParametersWidget.getLookupMetadata().getResultReturnKey()); 750 selectedValues.add(new SelectedResults(displayKey, returnKey, row)); 751 if (multiSelect == false) { 752 break; 753 } 754 } 755 } 756 757 return selectedValues; 758 } 759 760 public boolean isMultiSelect() { 761 return multiSelect; 762 } 763 764 public void setMultiSelect(boolean multiSelect) { 765 this.multiSelect = multiSelect; 766 } 767 768 private static class ParamListItems implements ListItems{ 769 770 private List<LookupParamMetadata> params = new ArrayList<LookupParamMetadata>(); 771 772 public ParamListItems(LookupMetadata meta){ 773 params = meta.getParams(); 774 } 775 776 public ParamListItems(List<LookupParamMetadata> params){ 777 this.params = params; 778 } 779 780 @Override 781 public List<String> getAttrKeys() { 782 return new ArrayList<String>(); 783 } 784 785 @Override 786 public String getItemAttribute(String id, String attrkey) { 787 return ""; 788 } 789 790 @Override 791 public int getItemCount() { 792 return params.size(); 793 } 794 795 @Override 796 public List<String> getItemIds() { 797 List<String> ids = new ArrayList<String>(); 798 for(LookupParamMetadata param: params){ 799 ids.add(param.getKey()); 800 } 801 return ids; 802 } 803 804 @Override 805 public String getItemText(String id) { 806 String itemText = id; 807 for(LookupParamMetadata param: params){ 808 if(param.getKey().equals(id)){ 809 //TODO this should be a message key 810 itemText = param.getName(); 811 break; 812 } 813 } 814 return itemText; 815 } 816 817 public Widget getWidget(String id){ 818 Widget w = null; 819 for(LookupParamMetadata param: params){ 820 if(param.getKey().equals(id)){ 821 w = DefaultWidgetFactory.getInstance().getWidget(param); 822 break; 823 } 824 } 825 return w; 826 } 827 828 public List<LookupParamMetadata> getParams() { 829 return params; 830 } 831 } 832 833 private String getMessage(final String msgKey) { 834 return Application.getApplicationContext().getMessage(msgKey); 835 } 836 837 public void addLookupChangedCallback(Callback<LookupMetadata> callback) { 838 lookupChangedCallbacks.add(callback); 839 } 840 841 //FIXME: Is an action complete callback really necessary here, couldn't this simply be a method to perform the seach action. 842 public Callback<Boolean> getActionCompleteCallback() { 843 return new Callback<Boolean>() { 844 845 @Override 846 public void exec(Boolean result) { 847 848 if (resultsSelected == true) { 849 List<SelectedResults> selectedItems = getSelectedValues(); 850 if (selectedItems.isEmpty()) 851 Window.alert("Please, select a value"); 852 else 853 { 854 for(Callback<List<SelectedResults>> callback: selectedCompleteCallbacks){ 855 callback.exec(selectedItems); 856 } 857 return; 858 } 859 } 860 861 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getMessage("select")); 862 resultsSelected = true; 863 864 SearchRequestInfo sr = getSearchRequest(); 865 // KSLAB2571 KSCM1326 - adding searchId for better message overriding. 866 String searchId = activeSearchParametersWidget.getLookupMetadata().getId(); 867 table.performSearch(searchId, sr, activeSearchParametersWidget.getLookupMetadata().getResults(), activeSearchParametersWidget.getLookupMetadata().getResultReturnKey(), activeSearchParametersWidget.getLookupMetadata().getResultDisplayKey(), true); 868 resultsTablePanel.setVisible(true); 869 List<HasSearchParam> userCriteria = new ArrayList<HasSearchParam>(); 870 List<HasSearchParam> searchParams = activeSearchParametersWidget.getSearchParams(); 871 872 //initialize search parameters if user entered values into search criteria fields in UI 873 for(HasSearchParam field: searchParams){ 874 SearchParamInfo param = field.getSearchParam(); 875 //TODO is this null check needed here? probably. assuming string here 876 //TODO make check more robust here/inserting params more robust 877 //do not pass to the search parameters that are empty 878 //FIXME hack - comparison to 'optional' - replace with check against 'optional' field and update related lookup metadata 879 if ((param.getValues().get(0) != null) && ((param.getValues().get(0).trim().isEmpty() == false) || (param.getKey().toLowerCase().indexOf("optional") == -1))) { 880 userCriteria.add(field); 881 } 882 } 883 showCriteriaChosen(userCriteria); 884 885 if (hasSearchParams){ 886 //Only display modify link if there are search parametes available. 887 if(!resultsShown){ 888 searchSelectorPanel.removeFromParent(); 889 modifySearchPanel = GWT.create(CollapsablePanel.class); 890 modifySearchPanel.initialise(getMessage("searchPanelModifySearch"), searchSelectorPanel, false); 891 modifySearchPanel.getLabel().addClickHandler(new ClickHandler(){ 892 @Override 893 public void onClick(ClickEvent event) { 894 resultsTablePanel.setVisible(false); 895 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 896 resultsSelected = false; 897 }}); 898 SearchPanel.this.layout.insert(modifySearchPanel, 0); 899 900 } 901 else{ 902 modifySearchPanel.close(); 903 } 904 } 905 resultsShown = true; 906 907 for(Callback<Boolean> callback: actionCompletedCallbacks){ 908 callback.exec( Boolean.valueOf(true)); 909 } 910 } 911 }; 912 } 913 914 public SearchRequestInfo getSearchRequest() { 915 if (activeSearchParametersWidget != null) { 916 return activeSearchParametersWidget.getSearchRequest(); 917 } 918 return null; 919 } 920 921 public void setActionCancelButtonGroup(ActionCancelGroup actionCancelButtons) { 922 this.actionCancelButtons = actionCancelButtons; 923 } 924 925 public String getSelectedLookupName() { 926 return selectedLookupName; 927 } 928 929 public void setSelectedLookupName(String selectedLookupName) { 930 this.selectedLookupName = selectedLookupName; 931 } 932 933 public void addSelectionCompleteCallback(Callback<List<SelectedResults>> callback){ 934 selectedCompleteCallbacks.add(callback); 935 } 936 937 public void addActionCompleteCallback(Callback<Boolean> callback){ 938 actionCompletedCallbacks.add(callback); 939 } 940 941 public String getActionLabel() { 942 return actionLabel; 943 } 944 945 public void setActionLabel(String actionLabel) { 946 if ((actionLabel != null) && (actionLabel.trim().length() > 0)) { 947 this.actionLabel = actionLabel; 948 } 949 } 950 951}