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