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