View Javadoc

1   package org.kuali.student.lum.common.client.widgets;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.List;
6   import java.util.Map;
7   
8   import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
9   import org.kuali.student.common.ui.client.configurable.mvc.WidgetConfigInfo;
10  import org.kuali.student.common.ui.client.configurable.mvc.binding.HasDataValueBinding;
11  import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
12  import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
13  import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
14  import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
15  import org.kuali.student.common.ui.client.mvc.Callback;
16  import org.kuali.student.common.ui.client.mvc.DataModel;
17  import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
18  import org.kuali.student.common.ui.client.mvc.HasDataValue;
19  import org.kuali.student.common.ui.client.widgets.KSDropDown;
20  import org.kuali.student.common.ui.client.widgets.KSItemLabel;
21  import org.kuali.student.common.ui.client.widgets.KSLabel;
22  import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
23  import org.kuali.student.common.ui.client.widgets.layout.VerticalFlowPanel;
24  import org.kuali.student.common.ui.client.widgets.list.KSSelectedList;
25  import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent;
26  import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler;
27  import org.kuali.student.common.ui.client.widgets.list.impl.SimpleListItems;
28  import org.kuali.student.common.ui.client.widgets.menus.KSListPanel;
29  import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
30  import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
31  import org.kuali.student.common.ui.client.widgets.search.KSPicker;
32  import org.kuali.student.r1.common.assembly.data.Data;
33  import org.kuali.student.r1.common.assembly.data.LookupMetadata;
34  import org.kuali.student.r1.common.assembly.data.LookupParamMetadata;
35  import org.kuali.student.r1.common.assembly.data.Metadata;
36  import org.kuali.student.r1.common.assembly.data.QueryPath;
37  import org.kuali.student.r1.common.assembly.data.Data.DataValue;
38  import org.kuali.student.r1.common.assembly.data.Data.Value;
39  import org.kuali.student.r2.core.search.dto.SearchParamInfo;
40  import org.kuali.student.r2.core.search.dto.SearchRequestInfo;
41  import org.kuali.student.r2.lum.clu.dto.MembershipQueryInfo;
42  
43  import com.google.gwt.core.client.GWT;
44  import com.google.gwt.dom.client.Style;
45  import com.google.gwt.event.dom.client.ClickEvent;
46  import com.google.gwt.event.dom.client.ClickHandler;
47  import com.google.gwt.event.logical.shared.CloseEvent;
48  import com.google.gwt.event.logical.shared.CloseHandler;
49  import com.google.gwt.event.shared.HandlerRegistration;
50  import com.google.gwt.user.client.Timer;
51  import com.google.gwt.user.client.ui.HTML;
52  import com.google.gwt.user.client.ui.Panel;
53  import com.google.gwt.user.client.ui.Widget;
54  
55  public class CluSetEditorWidget extends VerticalSectionView {
56  
57      private List<KSSelectedListPanelPair> selectedListPanelPairs = new ArrayList<KSSelectedListPanelPair>();
58      private DataModelDefinition modelDefinition;
59  //    private final List<HandlerRegistration> showClusetDetailsHandlerRegs = new ArrayList<HandlerRegistration>(); 
60      private final Map<String, HandlerRegistration> showCluRangeDetailsHandlerRegs = new HashMap<String, HandlerRegistration>();
61      private List<KSItemLabelPanelPair> itemLabelPanelPairs = new ArrayList<KSItemLabelPanelPair>();
62      protected static String cluSetType;
63      private String metadataId;
64      private static Map<String, DataModelDefinition> modelDefinitionCache = new HashMap<String, DataModelDefinition>();
65      private BlockingTask initializeTask = new BlockingTask("Initializing");
66      protected static boolean singularCluOnly;
67      private KSSelectedList approvedClusSelection;
68      
69      private enum CluSetManagementField {
70          APPROVED, PROPOSED, CLUSETS, RANGE
71      }
72      
73      public CluSetEditorWidget() {
74          super();
75      }
76  
77      public CluSetEditorWidget(CluSetRetriever cluSetRetriever, Enum<?> viewEnum,
78              String name, String modelId, boolean showTitle,
79              final Callback<Boolean> onReady, String cluSetType, boolean singularCluOnly) {
80          super(viewEnum, name, modelId, showTitle);
81          CluSetEditorWidget.cluSetType = cluSetType;
82          CluSetEditorWidget.singularCluOnly = singularCluOnly;
83          if (cluSetType != null && cluSetType.equals("kuali.cluSet.type.Program")) {
84              this.metadataId = "programSet";
85          } else {
86              this.metadataId = "courseSet";
87          }
88          KSBlockingProgressIndicator.addTask(initializeTask);
89          if (modelDefinitionCache.get(metadataId) == null) {
90              cluSetRetriever.getMetadata(metadataId, new Callback<Metadata>(){
91                  @Override
92                  public void exec(Metadata result) {
93                      DataModelDefinition def = new DataModelDefinition(result);
94                      modelDefinitionCache.put(metadataId, def);
95                      setDef(def);
96                      setupEditor();
97                      if (onReady != null) {
98                          onReady.exec(new Boolean(true));
99                      }
100                     KSBlockingProgressIndicator.removeTask(initializeTask);                
101                 }
102             });
103         } else {
104             DataModelDefinition def = modelDefinitionCache.get(metadataId);
105             setDef(def);
106             setupEditor();
107             if (onReady != null) {
108                 onReady.exec(new Boolean(true));
109             }
110             KSBlockingProgressIndicator.removeTask(initializeTask);                
111         }
112     }
113     
114     private void setDef(DataModelDefinition def) {
115         this.modelDefinition = def;
116     }
117     
118     public void setupEditor() {
119         String labelType = null;
120         if (cluSetType == null || !cluSetType.equals("kuali.cluSet.type.Program")) {
121             labelType = "Course";
122         } else {
123             labelType = "Program";
124         }
125         final CluSetEditOptionDropdown chooser = GWT.create(CluSetEditOptionDropdown.class);
126         SwitchSection clusetDetails = new SwitchSection(
127                 chooser,
128                 null);
129         clusetDetails.enableConfirmation(false);
130         // ****** Add Approved Clus *******
131         Section approvedClusSection = new VerticalSection();
132         FieldDescriptor approvedClusFd = addField(approvedClusSection, 
133                 CommonWidgetConstants.CLU_SET_APPROVED_CLUS_FIELD, 
134                 generateMessageInfo(CommonWidgetConstants.NEW_CLU_SET_CONTENT_APPROVED + labelType),
135                 null,
136                 null);
137         approvedClusSelection = (KSSelectedList) approvedClusFd.getFieldWidget();
138         KSListPanel approvedClusListPanel = approvedClusSelection.separateValuesPanel();
139         clusetDetails.addSection(approvedClusSection, CommonWidgetConstants.CLU_SET_SWAP_APPROVED_CLUS);
140         // END OF items related to Add Approved Clus
141 
142         // ****** Add Proposed Clus *******
143         Section proposedClusSection = new VerticalSection();
144         FieldDescriptor proposedClusFd = addField(proposedClusSection, 
145                 CommonWidgetConstants.CLU_SET_PROPOSED_CLUS_FIELD, 
146                 generateMessageInfo(CommonWidgetConstants.NEW_CLU_SET_CONTENT_PROPOSED + labelType),
147                 null,
148                 null);
149         final KSSelectedList proposedClusSelection = (KSSelectedList) proposedClusFd.getFieldWidget();
150         KSListPanel proposedClusListPanel = proposedClusSelection.separateValuesPanel();
151         clusetDetails.addSection(proposedClusSection, CommonWidgetConstants.CLU_SET_SWAP_PROPOSED_CLUS);
152         // END OF items related to Add Approved Clus
153 
154         // ****** Add Clu Range *******
155         KSItemLabel clusetRangeLabel = null;
156         if (displayField(CluSetManagementField.RANGE)) {
157             Section cluRangeSection = new VerticalSection();
158             final Picker cluSetRangePicker = configureSearch(CommonWidgetConstants.CLU_SET_CLU_SET_RANGE_EDIT_FIELD);
159             addField(cluRangeSection, 
160                     CommonWidgetConstants.CLU_SET_CLU_SET_RANGE_EDIT_FIELD, 
161                     generateMessageInfo(CommonWidgetConstants.NEW_CLU_SET_CONTENT_RANGE + labelType),
162                     cluSetRangePicker,
163                     null);
164             final CluSetRangeDataHelper clusetRangeModelHelper = new CluSetRangeDataHelper();
165             clusetRangeLabel = new KSItemLabel(true, true, clusetRangeModelHelper);
166             final KSItemLabel theClusetRangeLabel = clusetRangeLabel;
167             clusetRangeLabel.getElement().getStyle().setProperty("border", "solid 1px #cdcdcd");
168             clusetRangeLabel.getElement().getStyle().setProperty("width", "354px");
169             final FieldDescriptor cluRangeFieldDescriptor = addField(
170                     cluRangeSection, 
171                     CommonWidgetConstants.CLU_SET_CLU_SET_RANGE_FIELD, 
172                     null, 
173                     clusetRangeLabel,
174                     null);
175             cluRangeFieldDescriptor.setWidgetBinding(new CluSetRangeBinding(clusetRangeModelHelper));
176             cluSetRangePicker.getSearchWindow().addActionCompleteCallback(new Callback<Boolean>() {
177                 @Override
178                 public void exec(Boolean result) {
179                     cluSetRangePicker.getSearchWindow().hide();
180 //                  ((ModelWidgetBinding)cluRangeFieldDescriptor.getModelWidgetBinding()).setWidgetValue(widget, model, path)
181 //                  CluSetHelper cluSetHelper = CluSetHelper.wrap(model.getRoot());
182 //                  cluSetHelper.setCluRangeParams(value)
183                     final SearchRequestInfo searchRequest = cluSetRangePicker.getSearchWindow().getSearchRequest();
184                     String selectedSearchKey = searchRequest.getSearchKey();
185                     Data searchRequestData = CluSetRangeModelUtil.INSTANCE.toData(searchRequest, null);
186                     LookupMetadata lookupMetadata = null;
187 
188                     // look for the lookupMetaData corresponding to the searchRequest
189                     List<LookupMetadata> lookupMDs = new ArrayList<LookupMetadata>();
190                     lookupMDs.add(cluSetRangePicker.getInitLookupMetadata());
191                     lookupMetadata = findLookupMetadataByLookupId(selectedSearchKey, 
192                             lookupMDs, searchRequest.getParams());
193                     if (lookupMetadata == null || 
194                             !nullSafeEquals(lookupMetadata.getSearchTypeId(), 
195                                     selectedSearchKey)) {
196                         lookupMetadata = findLookupMetadataByLookupId(selectedSearchKey, 
197                                 cluSetRangePicker.getAdditionalLookupMetadata(),
198                                 searchRequest.getParams());
199                     }
200 
201                     addClusetItemViewHandler(clusetRangeModelHelper,
202                             theClusetRangeLabel,
203                             lookupMetadata,
204                             searchRequestData,
205                             searchRequest);
206                     theClusetRangeLabel.setHighlighted(true);
207                     new Timer() {
208                         @Override
209                         public void run() {
210                             theClusetRangeLabel.setHighlighted(false);
211                         }
212                     }.schedule(5000);
213                 }
214             });
215             clusetDetails.addSection(cluRangeSection, CommonWidgetConstants.CLU_SET_SWAP_CLU_SET_RANGE);
216         }
217         // END OF items related to Add Clu Range
218 
219         // ****** Add cluSets *******
220         KSListPanel cluSetsListPanel = null;
221         KSSelectedList cluSetsSelection = null;
222         if (displayField(CluSetManagementField.CLUSETS)) {
223             Section cluSetSection = new VerticalSection();
224             FieldDescriptor cluSetsTempFd = getFieldDescriptor( 
225                     CommonWidgetConstants.CLU_SET_CLU_SETS_FIELD, 
226                     generateMessageInfo(CommonWidgetConstants.NEW_CLU_SET_CONTENT_CLUSET + labelType),
227                     null,
228                     null);
229             KSSelectedList tempCluSetsSelection = (KSSelectedList) cluSetsTempFd.getFieldWidget();
230             WidgetConfigInfo config = tempCluSetsSelection.getConfig();
231             cluSetsSelection = new KSSelectedList(config, false);
232             cluSetsListPanel = cluSetsSelection.separateValuesPanel();
233             final FieldDescriptor cluSetsFd = addField(
234                     cluSetSection, 
235                     CommonWidgetConstants.CLU_SET_CLU_SETS_FIELD, 
236                     generateMessageInfo(CommonWidgetConstants.NEW_CLU_SET_CONTENT_CLUSET + labelType),
237                     cluSetsSelection, 
238                     null);
239             cluSetsFd.setWidgetBinding(new CluSetBinding());
240             clusetDetails.addSection(cluSetSection, CommonWidgetConstants.CLU_SET_SWAP_CLU_SETS);
241         }
242         // END OF items related to Add CluSets
243 
244         // display item type title if the list selected items is populated
245         // hide if the list becomes empty (thus the close listeners for each item
246         String contextName = (cluSetType != null && cluSetType.equals("kuali.cluSet.type.Program"))?
247                 "PROGRAMS" : "COURSES";
248         VerticalFlowPanel selectedValuesPanel = new VerticalFlowPanel();
249         selectedValuesPanel.getElement().getStyle().setPaddingTop(20, Style.Unit.PX);
250         VerticalFlowPanel approvedClusPanel = prepareValuesPanel(approvedClusListPanel, "APPROVED " + contextName);
251         approvedClusPanel.getElement().getStyle().setPaddingTop(15, Style.Unit.PX);
252         VerticalFlowPanel proposedClusPanel = prepareValuesPanel(proposedClusListPanel, "PROPOSED " + contextName);
253         proposedClusPanel.getElement().getStyle().setPaddingTop(15, Style.Unit.PX);
254         VerticalFlowPanel rangePanel = null;
255         if (displayField(CluSetManagementField.RANGE)) {
256             rangePanel = prepareValuesPanel(clusetRangeLabel, contextName + " RANGE");
257             rangePanel.getElement().getStyle().setPaddingTop(15, Style.Unit.PX);
258         }
259         VerticalFlowPanel cluSetsPanel = null;
260         if (displayField(CluSetManagementField.CLUSETS)) {
261             cluSetsPanel = prepareValuesPanel(cluSetsListPanel, contextName + " SETS");
262             cluSetsPanel.getElement().getStyle().setPaddingTop(15, Style.Unit.PX);
263         }
264         
265         selectedValuesPanel.add(approvedClusPanel);
266         selectedValuesPanel.add(proposedClusPanel);
267         if (displayField(CluSetManagementField.RANGE)) {
268             selectedValuesPanel.add(rangePanel);
269         }
270         if (displayField(CluSetManagementField.CLUSETS)) {
271             selectedValuesPanel.add(cluSetsPanel);
272         }
273 
274         addVisibilityHandlers(approvedClusSelection, approvedClusPanel);
275         addVisibilityHandlers(proposedClusSelection, proposedClusPanel);
276         if (displayField(CluSetManagementField.RANGE)) {
277             addVisibilityHandlers(clusetRangeLabel, rangePanel);
278         }
279         if (displayField(CluSetManagementField.CLUSETS)) {
280             addVisibilityHandlers(cluSetsSelection, cluSetsPanel);
281         }
282         
283         selectedListPanelPairs.add(new KSSelectedListPanelPair(approvedClusSelection, approvedClusPanel));
284         selectedListPanelPairs.add(new KSSelectedListPanelPair(proposedClusSelection, proposedClusPanel));
285         if (displayField(CluSetManagementField.CLUSETS)) {
286             selectedListPanelPairs.add(new KSSelectedListPanelPair(cluSetsSelection, cluSetsPanel));
287         }
288         if (displayField(CluSetManagementField.RANGE)) {
289             itemLabelPanelPairs.add(new KSItemLabelPanelPair(clusetRangeLabel, rangePanel));
290         }
291         
292         final VerticalSection choosingSection = new VerticalSection();
293         HTML prompt;
294         if(cluSetType.equals("kuali.cluSet.type.Program")){
295             choosingSection.addWidget(new HTML("<b>Add a program or program set</b>"));
296             prompt = new HTML("Add program or program sets. You may  <br/>"
297                     + "add any combination of programs or program sets.");
298         }
299         else{
300             choosingSection.addWidget(new HTML("<b>Add a course, course set, or course range</b>"));
301             prompt = new HTML("Add courses, course sets, or course ranges to your course set. You may <br/>" +
302                 "add any combination of courses, dynamic course ranges, or Course sets.");
303         }
304         choosingSection.addWidget(chooser);
305         choosingSection.addSection(clusetDetails);
306         chooser.addSelectionChangeHandler(new SelectionChangeHandler() {
307             @Override
308             public void onSelectionChange(SelectionChangeEvent event) {
309                 if (chooser.getSelectedItem() != null &&
310                         !chooser.getSelectedItem().trim().isEmpty()) {
311                     choosingSection.setStyleName("KS-CluSetManagement-chooser");
312                 } else {
313                     choosingSection.setStyleName("KS-CluSetManagement-chooser-unselected");
314                 }
315             }
316         });
317         
318         this.addWidget(prompt);
319         this.addSection(choosingSection);
320         this.addWidget(selectedValuesPanel);
321     }
322     
323     private boolean displayField(CluSetManagementField field) {
324         boolean result = false;
325         switch(field) {
326             case APPROVED:
327             case PROPOSED:
328                 result = true;
329                 break;
330             case RANGE:
331                 if (!singularCluOnly && (cluSetType == null || !cluSetType.equals("kuali.cluSet.type.Program"))) {
332                     result = true;
333                 } else {
334                     result = false;
335                 }
336                 break;
337             case CLUSETS:
338                 if (!singularCluOnly) {
339                     result = true;
340                 } else {
341                     result = false;
342                 }
343                 break;
344         }
345         return result;
346     }
347     
348     private void addClusetItemViewHandler(CluSetRangeDataHelper clusetRangeModelHelper,
349             KSItemLabel clusetRangeLabel,
350             final LookupMetadata lookupMetadata,
351             Data searchRequestData,
352             final SearchRequestInfo searchRequest) {
353         clusetRangeModelHelper.setLookupMetadata(lookupMetadata);
354         clusetRangeLabel.setValue(new DataValue(searchRequestData));
355         if (showCluRangeDetailsHandlerRegs != null && 
356                 showCluRangeDetailsHandlerRegs.get(Integer.toString(clusetRangeLabel.instanceId)) != null) {
357             ((HandlerRegistration)showCluRangeDetailsHandlerRegs.get(Integer.toString(clusetRangeLabel.instanceId))).removeHandler();
358         }
359         showCluRangeDetailsHandlerRegs.put(Integer.toString(clusetRangeLabel.instanceId), 
360                 clusetRangeLabel.addShowDetailsHandler(new ClickHandler() {
361             @Override
362             public void onClick(ClickEvent event) {
363                 SearchResultsLightBox srLightBox = new SearchResultsLightBox("View Course Range",
364                         searchRequest, lookupMetadata);
365                 srLightBox.show();
366             }
367         }));
368     }
369     
370     protected MessageKeyInfo generateMessageInfo(String labelKey) {
371         return new MessageKeyInfo("clusetmanagement", "clusetmanagement", "draft", labelKey);
372     }
373     
374     private FieldDescriptor getFieldDescriptor( 
375             String fieldKey, 
376             MessageKeyInfo messageKey, 
377             Widget widget, 
378             String parentPath) {
379         QueryPath path = QueryPath.concat(parentPath, fieldKey);
380         Metadata meta = modelDefinition.getMetadata(path);
381         FieldDescriptor fd;
382         if (widget != null) {
383             fd = new FieldDescriptor(path.toString(), messageKey, meta, widget);
384         }
385         else{
386             fd = new FieldDescriptor(path.toString(), messageKey, meta);
387         }
388         return fd;
389     }
390 
391     private FieldDescriptor addField(Section section, 
392             String fieldKey, 
393             MessageKeyInfo messageKey, 
394             Widget widget, 
395             String parentPath) {
396         FieldDescriptor fd = getFieldDescriptor(fieldKey, messageKey, widget, parentPath);
397         section.addField(fd);
398         return fd;
399     }
400 
401     private static boolean nullSafeEquals(Object obj1, Object obj2) {
402         return (obj1 == null && obj2 == null ||
403                 obj1 != null && obj2 != null && obj1.equals(obj2));
404     }
405     
406     private VerticalFlowPanel prepareValuesPanel(Widget widget, String title) {
407         final VerticalFlowPanel valuesPanel = new VerticalFlowPanel();
408         valuesPanel.add(new KSLabel(title));
409         valuesPanel.add(widget);
410         valuesPanel.setVisible(false);
411         return valuesPanel;
412     }
413     
414     @Override
415     public void updateWidgetData(DataModel model) {
416         super.updateWidgetData(model);
417         // this is to refresh the lists and item labels.
418         if (selectedListPanelPairs != null) {
419             for (KSSelectedListPanelPair selectedListPanelPair : selectedListPanelPairs) {
420                 handleSelectedListVisibility(selectedListPanelPair.getKsSelectedList(), 
421                         selectedListPanelPair.getPanel());
422             }
423         }
424         if (itemLabelPanelPairs != null) {
425             for (KSItemLabelPanelPair itemLabelPanelPair : itemLabelPanelPairs) {
426                 handleListItemVisibility(itemLabelPanelPair.getKsItemLabel(), 
427                         itemLabelPanelPair.getPanel());
428             }
429         }
430     }
431 
432     private void addVisibilityHandlers(final KSItemLabel listItem,
433             final Panel selectionPanel) {
434         listItem.addValueChangeCallback(new Callback<Value>() {
435             @Override
436             public void exec(Value result) {
437                 handleListItemVisibility(listItem, selectionPanel);
438             }
439         });
440     }
441     
442     private void handleListItemVisibility(KSItemLabel listItem, Panel selectionPanel) {
443         String displayText = listItem.getDisplayText();
444         if (displayText == null || displayText.equals("")) {
445             selectionPanel.setVisible(false);
446         } else {
447             selectionPanel.setVisible(true);
448         }
449     }
450     
451     private void addVisibilityHandlers(final KSSelectedList selectionList,
452             final Panel selectionPanel) {
453         selectionList.addSelectionChangeHandler(
454                 new SelectionChangeHandler() {
455                     @Override
456                     public void onSelectionChange(SelectionChangeEvent event) {
457                         handleSelectedListVisibility(selectionList, selectionPanel);
458                     }
459                 }
460         );
461     }
462     
463     private void handleSelectedListVisibility(final KSSelectedList selectionList, final Panel selectionPanel) {
464         List<KSItemLabel> selectedItems = selectionList.getSelectedItems();
465         if (selectedItems != null && !selectedItems.isEmpty()) {
466             // show item type title
467             selectionPanel.setVisible(true);
468             for (KSItemLabel selectedItem : selectedItems) {
469                 selectedItem.addCloseHandler(new CloseHandler<KSItemLabel>() {
470                     @Override
471                     public void onClose(CloseEvent<KSItemLabel> event) {
472                         List<KSItemLabel> newSelectedItems = 
473                             selectionList.getSelectedItems();
474                         int numNewSelectedItems = (newSelectedItems == null)? 0 :
475                             newSelectedItems.size();
476                         if (numNewSelectedItems == 0) {
477                             //hide item type title
478                             selectionPanel.setVisible(false);
479                         }
480                     }
481                 });
482             }
483         }
484     }
485 
486     private Picker configureSearch(String fieldKey) {
487         QueryPath path = QueryPath.concat(null, fieldKey);
488         Metadata metaData = modelDefinition.getMetadata(path);
489         Picker picker = new Picker(metaData.getInitialLookup(), metaData.getAdditionalLookups());
490         return picker;
491     }
492 
493     private static LookupMetadata findLookupMetadataByLookupId(String searchTypeId,
494             List<LookupMetadata> lookupMetadatas,
495             List<SearchParamInfo> searchParams) {
496         LookupMetadata result = null;
497         if (lookupMetadatas != null) {
498             for (LookupMetadata lookupMetadata : lookupMetadatas) {
499                 if (nullSafeEquals(lookupMetadata.getSearchTypeId(), searchTypeId)) {
500                     // search Type id matches now add up all the params meta found to the result
501                     List<LookupParamMetadata> paramMetas = lookupMetadata.getParams();
502                     List<LookupParamMetadata> resultParamMetas = null;
503                     result = (result == null)? new LookupMetadata() : result;
504                     result.setDesc(lookupMetadata.getDesc());
505                     result.setId(lookupMetadata.getId());
506                     result.setName("");
507                     resultParamMetas = result.getParams();
508                     if (resultParamMetas == null) {
509                         resultParamMetas = new ArrayList<LookupParamMetadata>();
510                     }
511                     if (paramMetas != null) {
512                         for (LookupParamMetadata paramMeta : paramMetas) {
513                             boolean resultParamMetaFound = false;
514                             for (LookupParamMetadata resultParamMeta : resultParamMetas) {
515                                 if (paramMeta.getKey().equals(resultParamMeta)) {
516                                     resultParamMetaFound = true;
517                                     break;
518                                 }
519                             }
520                             if (!resultParamMetaFound) {
521                                 resultParamMetas.add(paramMeta);
522                             }
523                         }
524                     }
525                     result.setParams(resultParamMetas);
526                     result.setQosMetadata(lookupMetadata.getQosMetadata());
527                     result.setResultDisplayKey(lookupMetadata.getResultDisplayKey());
528                     result.setResultReturnKey(lookupMetadata.getResultReturnKey());
529                     result.setResults(lookupMetadata.getResults());
530                     result.setResultSortKey(lookupMetadata.getResultSortKey());
531                 }
532             }
533         }
534         return result;
535     }
536     
537     @Override
538     public void updateModel() {
539         
540         super.updateModel();
541     }
542 
543 
544 
545     public static class CluSetEditOptionDropdown extends KSDropDown {
546         public CluSetEditOptionDropdown(){
547             SimpleListItems editOptions = new SimpleListItems();
548 
549             if (cluSetType != null && cluSetType.equals("kuali.cluSet.type.Program")) {
550                 editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_APPROVED_CLUS, "Approved Programs");
551                 editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_PROPOSED_CLUS, "Proposed Programs");
552                 if (!singularCluOnly) {
553                     editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_CLU_SETS, "Program Sets");
554                 }
555             } else {
556                 editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_APPROVED_CLUS, "Approved Courses");
557                 editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_PROPOSED_CLUS, "Proposed Courses");
558                 if (!singularCluOnly) {
559                     editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_CLU_SETS, "Course Sets");
560                     editOptions.addItem(CommonWidgetConstants.CLU_SET_SWAP_CLU_SET_RANGE, "Course Ranges (Course numbers, common learning objectives, etc)");
561                 }
562             }
563             super.setListItems(editOptions);
564         }
565     }
566 
567     class KSSelectedListPanelPair {
568         private KSSelectedList ksSelectedList;
569         private Panel panel;
570         public KSSelectedListPanelPair(KSSelectedList ksSelectedList, Panel panel) {
571             setKsSelectedList(ksSelectedList);
572             setPanel(panel);
573         }
574         public KSSelectedList getKsSelectedList() {
575             return ksSelectedList;
576         }
577         public void setKsSelectedList(KSSelectedList ksSelectedList) {
578             this.ksSelectedList = ksSelectedList;
579         }
580         public Panel getPanel() {
581             return panel;
582         }
583         public void setPanel(Panel panel) {
584             this.panel = panel;
585         }
586     }
587     
588     class KSItemLabelPanelPair {
589         private KSItemLabel ksItemLabel;
590         private Panel panel;
591         public KSItemLabelPanelPair(KSItemLabel ksItemLabel, Panel panel) {
592             setKsItemLabel(ksItemLabel);
593             setPanel(panel);
594         }
595         public KSItemLabel getKsItemLabel() {
596             return ksItemLabel;
597         }
598         public void setKsItemLabel(KSItemLabel ksItemLabel) {
599             this.ksItemLabel = ksItemLabel;
600         }
601         public Panel getPanel() {
602             return panel;
603         }
604         public void setPanel(Panel panel) {
605             this.panel = panel;
606         }
607     }
608     
609     public static class Picker extends KSPicker {
610 
611         private String name;
612         private LookupMetadata initLookupMetadata;
613         private List<LookupMetadata> additionalLookupMetadata;
614 
615         public Picker(LookupMetadata inLookupMetadata, List<LookupMetadata> additionalLookupMetadata) {
616             super(inLookupMetadata, additionalLookupMetadata);
617             this.initLookupMetadata = inLookupMetadata;
618             this.additionalLookupMetadata = additionalLookupMetadata;
619         }
620 
621         public String getName() {
622             return name;
623         }
624 
625         public void setName(String name) {
626             this.name = name;
627         }
628 
629         public LookupMetadata getInitLookupMetadata() {
630             return initLookupMetadata;
631         }
632 
633         public void setInitLookupMetadata(LookupMetadata initLookupMetadata) {
634             this.initLookupMetadata = initLookupMetadata;
635         }
636 
637         public List<LookupMetadata> getAdditionalLookupMetadata() {
638             return additionalLookupMetadata;
639         }
640 
641         public void setAdditionalLookupMetadata(List<LookupMetadata> additionalLookupMetadata) {
642             this.additionalLookupMetadata = additionalLookupMetadata;
643         }
644         
645     }
646     
647     public class CluSetBinding extends ModelWidgetBindingSupport<HasDataValue> {
648         private HasDataValueBinding binding = HasDataValueBinding.INSTANCE;
649 
650         @Override
651         public void setModelValue(HasDataValue widget, DataModel model, String path) {
652             binding.setModelValue(widget, model, path);
653         }
654 
655         @Override
656         public void setWidgetValue(HasDataValue widget, DataModel model, String path) {
657             binding.setWidgetValue(widget, model, path);
658         }
659     }
660     
661     public class CluSetRangeBinding extends ModelWidgetBindingSupport<HasDataValue> {
662         private HasDataValueBinding binding = HasDataValueBinding.INSTANCE;
663         private CluSetRangeDataHelper clusetRangeModelHelper = null;
664         
665         public CluSetRangeBinding(CluSetRangeDataHelper clusetRangeModelHelper) {
666             this.clusetRangeModelHelper = clusetRangeModelHelper;
667         }
668         
669         @Override
670         public void setModelValue(HasDataValue widget, DataModel model, String path) {
671             binding.setModelValue(widget, model, path);
672         }
673 
674         @Override
675         public void setWidgetValue(final HasDataValue widget, DataModel model, String path) {
676             DataModel middleManModel = new DataModel();
677             if (model != null && model.getRoot() != null) {
678                 middleManModel = new DataModel(model.getDefinition(), model.getRoot().copy());
679             }
680             Metadata rangeEditMetaData = model.getMetadata(
681                     QueryPath.parse(CommonWidgetConstants.CLU_SET_CLU_SET_RANGE_EDIT_FIELD));
682             Data membershipQueryData = (Data)model.get(path);
683             MembershipQueryInfo membershipQueryInfo = (membershipQueryData == null)?
684                     null : CluSetRangeModelUtil.INSTANCE.toMembershipQueryInfo(membershipQueryData);
685             if (membershipQueryInfo != null) {
686                 String selectedSearchTypeKey = membershipQueryInfo.getSearchTypeKey();
687                 List<LookupMetadata> lookupMDs = new ArrayList<LookupMetadata>();
688                 List<SearchParamInfo> searchParams = membershipQueryInfo.getQueryParamValues();
689                 lookupMDs.add(rangeEditMetaData.getInitialLookup());
690                 LookupMetadata lookupMetadata = findLookupMetadataByLookupId(selectedSearchTypeKey, 
691                         lookupMDs, searchParams);
692                 if (lookupMetadata == null || 
693                         !nullSafeEquals(lookupMetadata.getName(), 
694                                 selectedSearchTypeKey)) {
695                     lookupMetadata = findLookupMetadataByLookupId(selectedSearchTypeKey, 
696                             rangeEditMetaData.getAdditionalLookups(), searchParams);
697                 }
698 
699                 SearchRequestInfo searchRequest = new SearchRequestInfo();
700                 searchRequest.setSearchKey(selectedSearchTypeKey);
701 //              if ()
702                 searchRequest.setParams(searchParams);
703                 searchRequest.setSortColumn(lookupMetadata.getResultSortKey());
704                 
705 //                if (showCluRangeDetailsHandlerRegs != null) {
706 //                    for (HandlerRegistration showCluRangeDetailsHandlerReg : showCluRangeDetailsHandlerRegs) {
707 //                        showCluRangeDetailsHandlerReg.removeHandler();
708 //                    }
709 //                    showCluRangeDetailsHandlerRegs.clear();
710 //                }
711                 addClusetItemViewHandler(clusetRangeModelHelper,
712                         (KSItemLabel)widget,
713                         lookupMetadata,
714                         membershipQueryData,
715                         searchRequest);
716                 ((KSItemLabel)widget).setHighlighted(true);
717                 new Timer() {
718                     @Override
719                     public void run() {
720                         ((KSItemLabel)widget).setHighlighted(false);
721                     }
722                 }.schedule(5000);
723             }
724             binding.setWidgetValue(widget, middleManModel, path);
725         }
726     }
727 }