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