View Javadoc

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.lum.lu.ui.tools.client.configuration;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.kuali.student.common.assembly.data.Data;
24  import org.kuali.student.common.assembly.data.LookupMetadata;
25  import org.kuali.student.common.assembly.data.Metadata;
26  import org.kuali.student.common.assembly.data.QueryPath;
27  import org.kuali.student.common.assembly.data.Data.DataValue;
28  import org.kuali.student.common.search.dto.SearchRequest;
29  import org.kuali.student.common.ui.client.application.Application;
30  import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
31  import org.kuali.student.common.ui.client.configurable.mvc.LayoutController;
32  import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
33  import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.DisplayMultiplicityComposite;
34  import org.kuali.student.common.ui.client.configurable.mvc.sections.GroupSection;
35  import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
36  import org.kuali.student.common.ui.client.configurable.mvc.sections.SwapSection;
37  import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
38  import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
39  import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
40  import org.kuali.student.common.ui.client.mvc.Callback;
41  import org.kuali.student.common.ui.client.mvc.DataModel;
42  import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
43  import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
44  import org.kuali.student.common.ui.client.widgets.KSDatePicker;
45  import org.kuali.student.common.ui.client.widgets.KSItemLabel;
46  import org.kuali.student.common.ui.client.widgets.KSLabel;
47  import org.kuali.student.common.ui.client.widgets.KSTextArea;
48  import org.kuali.student.common.ui.client.widgets.dialog.ConfirmationDialog;
49  import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
50  import org.kuali.student.common.ui.client.widgets.list.KSCheckBoxList;
51  import org.kuali.student.common.ui.client.widgets.list.impl.SimpleListItems;
52  import org.kuali.student.common.ui.client.widgets.search.KSPicker;
53  import org.kuali.student.common.ui.client.widgets.search.SelectedResults;
54  import org.kuali.student.lum.common.client.lu.LUUIConstants;
55  import org.kuali.student.lum.common.client.widgets.CluSetRangeDataHelper;
56  import org.kuali.student.lum.common.client.widgets.CluSetRangeModelUtil;
57  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
58  import org.kuali.student.lum.lu.dto.MembershipQueryInfo;
59  
60  import com.google.gwt.core.client.GWT;
61  import com.google.gwt.user.client.ui.Widget;
62  
63  public class CluSetsConfigurer {
64  
65      private boolean WITH_DIVIDER = true;
66  
67      public static final String CREATE_CLUSET_MGT_MODEL = "createCluSetManagementModel";
68      public static final String EDIT_CLUSET_MGT_MODEL = "editCluSetManagementModel";
69      public static final String VIEW_CLUSET_MGT_MODEL = "viewCluSetManagerModel";
70      public static final String EDIT_SEARCH_CLUSET_MGT_MODEL = "editSearchCluSetManagementModel";
71      public static final String VIEW_SEARCH_CLUSET_MGT_MODEL = "viewSearchCluSetManagementModel";
72      private String editSearchCluSetId = null;
73      private String viewSearchCluSetId = null;
74      private Map<String, CluSetEditOptionList> cluSetEditOptionsMap =
75          new HashMap<String, CluSetEditOptionList>();
76  
77  
78      private DataModelDefinition modelDefinition;
79  
80      public enum CluSetSections{
81          CREATE_CLU_SET, EDIT_CLU_SET, VIEW_CLU_SET
82      }
83  
84      public void setModelDefinition(DataModelDefinition modelDefinition){
85      	this.modelDefinition = modelDefinition;
86      }
87  
88  //    public void configureCluSetManager(ConfigurableLayout layout) {
89  //        SectionView createCluSetView = createCluSetSection();
90  //        SectionView editCluSetView = editCluSetSection();
91  //        CluSetsModelDispatcher createCluSetModelDispatcher = new CluSetsModelDispatcher();
92  //        CluSetsModelDispatcher editCluSetModelDispatcher = new CluSetsModelDispatcher();
93  //
94  //        createCluSetModelDispatcher.setModelId(CluSetsConfigurer.CREATE_CLUSET_MGT_MODEL);
95  //        createCluSetView.setLayoutController(createCluSetModelDispatcher);
96  //        createCluSetView.setController(createCluSetModelDispatcher);
97  //
98  //        editCluSetModelDispatcher.setModelId(CluSetsConfigurer.EDIT_CLUSET_MGT_MODEL);
99  //        editCluSetView.setLayoutController(editCluSetModelDispatcher);
100 //        editCluSetView.setController(editCluSetModelDispatcher);
101 ////        addStartSection(layout);
102 //        layout.addSection(new String[] {"Manage CLU Sets", getLabel(ToolsConstants.NEW_CLU_SET_LABEL_KEY)}, createCluSetView);
103 //        layout.addSection(new String[] {"Manage CLU Sets", getLabel(ToolsConstants.NEW_CLU_SET_LABEL_KEY)}, editCluSetView);
104 //        layout.addSection(new String[] {"View CLU Sets"}, viewCluSetSection());
105 //    }
106 
107     private void addClusetDetailsSections(SectionView parentView, final String modelId) {
108         VerticalSection defineCluSet = initSection(getH3Title(ToolsConstants.NEW_CLU_SET_INFO), WITH_DIVIDER);
109         CluSetEditOptionList cluSetEditOptions = new CluSetEditOptionList();
110         cluSetEditOptionsMap.put(modelId, cluSetEditOptions);
111         SwapSection clusetDetails = new SwapSection(
112                 cluSetEditOptions,
113                 new ConfirmationDialog("Delete Clu Set Details",
114                         "You are about to delete clu set details.  Continue?")
115                 );
116         
117         ModelIdPlaceHolder modelIdObj = new ModelIdPlaceHolder(modelId);
118 
119         // ****** Add Approved Clus *******
120         Section approvedClusSection = new VerticalSection();
121         addField(approvedClusSection, ToolsConstants.CLU_SET_APPROVED_CLUS_FIELD, generateMessageInfo(ToolsConstants.NEW_CLU_SET_CONTENT_APPROVED_COURSE)).setModelId(modelId);
122         clusetDetails.addSection(approvedClusSection, ToolsConstants.CLU_SET_SWAP_APPROVED_CLUS);
123         // END OF items related to Add Approved Clus
124 
125         // ****** Add Proposed Clus *******
126         Section proposedClusSection = new VerticalSection();
127         addField(proposedClusSection, ToolsConstants.CLU_SET_PROPOSED_CLUS_FIELD, generateMessageInfo(ToolsConstants.NEW_CLU_SET_CONTENT_PROPOSED_COURSE)).setModelId(modelId);
128         clusetDetails.addSection(proposedClusSection, ToolsConstants.CLU_SET_SWAP_PROPOSED_CLUS);
129         // END OF items related to Add Approved Clus
130 
131         // ****** Add Clu Range *******
132         //TODO add cluset and clurange here
133         Section cluRangeSection = new VerticalSection();
134         final Picker cluSetRangePicker = configureSearch(ToolsConstants.CLU_SET_CLU_SET_RANGE_EDIT_FIELD);
135         final FieldDescriptor cluRangeFieldEditDescriptor = addField(cluRangeSection, ToolsConstants.CLU_SET_CLU_SET_RANGE_EDIT_FIELD, generateMessageInfo(ToolsConstants.NEW_CLU_SET_CONTENT_RANGE), cluSetRangePicker);
136         final CluSetRangeDataHelper clusetRangeModelHelper = new CluSetRangeDataHelper();
137         final KSItemLabel clusetRangeLabel = new KSItemLabel(true, clusetRangeModelHelper);
138         clusetRangeLabel.getElement().getStyle().setProperty("border", "solid 1px #cdcdcd");
139         final FieldDescriptor cluRangeFieldDescriptor = addField(cluRangeSection, ToolsConstants.CLU_SET_CLU_SET_RANGE_FIELD, null, clusetRangeLabel);
140         cluSetRangePicker.getSearchWindow().addActionCompleteCallback(new Callback<Boolean>() {
141         
142             @Override
143             public void exec(Boolean result) {
144                 cluSetRangePicker.getSearchWindow().hide();
145                 final LayoutController parent = LayoutController.findParentLayout(cluSetRangePicker);
146                 if(parent != null){
147                     parent.requestModel(modelId, new ModelRequestCallback<DataModel>() {
148                         @Override
149                         public void onModelReady(DataModel model) {
150 //                            ((ModelWidgetBinding)cluRangeFieldDescriptor.getModelWidgetBinding()).setWidgetValue(widget, model, path)
151 //                            CluSetHelper cluSetHelper = CluSetHelper.wrap(model.getRoot());
152 //                            cluSetHelper.setCluRangeParams(value)
153                             SearchRequest searchRequest = cluSetRangePicker.getSearchWindow()
154                                 .getSearchRequest();
155                             String selectedLookupName = cluSetRangePicker.getSearchWindow()
156                                 .getSelectedLookupName();
157                             Data searchRequestData = CluSetRangeModelUtil.INSTANCE.
158                                 toData(searchRequest, null);
159                             DataValue dataValue = new DataValue(searchRequestData);
160                             LookupMetadata lookupMetadata = null;
161                             
162                             // look for the lookupMetaData corresponding to the searchRequest
163                             List<LookupMetadata> lookupMDs = new ArrayList<LookupMetadata>();
164                             lookupMDs.add(cluSetRangePicker.getInitLookupMetadata());
165                             lookupMetadata = findLookupMetadata(selectedLookupName, 
166                                     lookupMDs);
167                             if (lookupMetadata == null || 
168                                     !nullSafeEquals(lookupMetadata.getName(), 
169                                             selectedLookupName)) {
170                                 lookupMetadata = findLookupMetadata(selectedLookupName, 
171                                         cluSetRangePicker.getAdditionalLookupMetadata());
172                             }
173                             
174                             clusetRangeModelHelper.setLookupMetadata(lookupMetadata);
175                             clusetRangeLabel.setValue(dataValue);
176                         }
177 
178                         @Override
179                         public void onRequestFail(Throwable cause) {
180                             GWT.log("Unable to retrieve model" + cluRangeFieldDescriptor.getFieldKey(), null);
181                         }
182                         
183                     });
184                 }
185             }
186         });
187         clusetDetails.addSection(cluRangeSection, ToolsConstants.CLU_SET_SWAP_CLU_SET_RANGE);
188         // END OF items related to Add Clu Range
189         // ****** Add cluSets *******
190         Section cluSetSection = new VerticalSection();
191         addField(cluSetSection, ToolsConstants.CLU_SET_CLU_SETS_FIELD, generateMessageInfo(ToolsConstants.NEW_CLU_SET_CONTENT_CLUSET)).setModelId(modelId);
192         clusetDetails.addSection(cluSetSection, ToolsConstants.CLU_SET_SWAP_CLU_SETS);
193         // END OF items related to Add CluSets
194         
195         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_TYPE_FIELD);
196         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_ORGANIZATION_FIELD, generateMessageInfo(ToolsConstants.ORGANIZATION));
197         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_NAME_FIELD, generateMessageInfo(ToolsConstants.TITLE));
198         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_DESCRIPTION_FIELD, generateMessageInfo(ToolsConstants.DESCRIPTION), new KSTextArea());
199         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_EFF_DATE_FIELD, generateMessageInfo(ToolsConstants.EFFECTIVE_DATE), new KSDatePicker());
200         addField(modelIdObj, defineCluSet, ToolsConstants.CLU_SET_EXP_DATE_FIELD, generateMessageInfo(ToolsConstants.EXPIRATION_DATE), new KSDatePicker());
201         
202         parentView.addWidget(cluSetEditOptions);
203         parentView.addSection(clusetDetails);
204         parentView.addSection(defineCluSet);
205     }
206     
207     private static boolean nullSafeEquals(Object obj1, Object obj2) {
208         return (obj1 == null && obj2 == null ||
209                 obj1 != null && obj2 != null && obj1.equals(obj2));
210     }
211     
212     private static LookupMetadata findLookupMetadata(String selectedLookupName, 
213             List<LookupMetadata> lookupMetadatas) {
214         LookupMetadata result = null;
215         if (lookupMetadatas != null) {
216             for (LookupMetadata lookupMetadata : lookupMetadatas) {
217                 if (nullSafeEquals(lookupMetadata.getName(), selectedLookupName)) {
218                     result = lookupMetadata;
219                 }
220             }
221         }
222         return result;
223     }
224 
225     private SectionView createCluSetSection() {
226         // TODO change this to custom layoutcontroller here to support multiple model ids?
227         VerticalSectionView section = initNestedSectionView(CluSetSections.CREATE_CLU_SET, ToolsConstants.NEW_CLU_SET, CREATE_CLUSET_MGT_MODEL);
228         addClusetDetailsSections(section, CluSetsConfigurer.CREATE_CLUSET_MGT_MODEL);
229         return section;
230 	}
231 
232     private boolean hasCluSetRange(Data cluSetRangeData) {
233         boolean hasCluSetRange = false;
234         MembershipQueryInfo membershipQueryInfo = 
235             CluSetRangeModelUtil.INSTANCE.toMembershipQueryInfo(cluSetRangeData);
236         if (membershipQueryInfo != null) {
237             hasCluSetRange = true;
238         }
239         return hasCluSetRange;
240     }
241     
242     private boolean hasClus(Data clusData) {
243         boolean clusExist = false;
244         if (clusData != null) {
245             for (Data.Property p : clusData) {
246                 if(!"_runtimeData".equals(p.getKey())){
247                     String cluId = p.getValue();
248                     if (cluId != null && !cluId.trim().isEmpty()) {
249                         clusExist = true;
250                         break;
251                     }
252                 }
253             }
254         }
255         return clusExist;
256     }
257     
258     private boolean hasCluSets(Data clusetData) {
259         boolean cluSetsExist = false;
260         if (clusetData != null) {
261             for (Data.Property p : clusetData) {
262                 if(!"_runtimeData".equals(p.getKey())){
263                     String cluSetId = p.getValue();
264                     if (cluSetId != null && !cluSetId.trim().isEmpty()) {
265                         cluSetsExist = true;
266                         break;
267                     }
268                 }
269             }
270         }
271         return cluSetsExist;
272     }
273     
274     private boolean hasData(String queryPath, Data queryData) {
275         boolean hasData = false;
276         if (queryPath != null && (queryPath.equals(ToolsConstants.CLU_SET_APPROVED_CLUS_FIELD) ||
277                 queryPath.equals(ToolsConstants.CLU_SET_PROPOSED_CLUS_FIELD))) {
278             hasData = hasClus(queryData);
279         } else if (queryPath != null && queryPath.equals(ToolsConstants.CLU_SET_CLU_SETS_FIELD)) {
280             hasData = hasCluSets(queryData);
281         } else if (queryPath != null && queryPath.equals(ToolsConstants.CLU_SET_CLU_SET_RANGE_FIELD)) {
282             hasData = hasCluSetRange(queryData);
283         } else {
284             throw new IllegalArgumentException("Unexpected queryPath: " + queryPath);
285         }
286         return hasData;
287     }
288     
289     private void selectCluSetOptionList(DataModel model, CluSetEditOptionList cluSetEditOptions) {
290         selectCluSetOption(model, cluSetEditOptions, ToolsConstants.CLU_SET_APPROVED_CLUS_FIELD,
291                 ToolsConstants.CLU_SET_SWAP_APPROVED_CLUS);
292         selectCluSetOption(model, cluSetEditOptions, ToolsConstants.CLU_SET_PROPOSED_CLUS_FIELD, 
293                 ToolsConstants.CLU_SET_SWAP_PROPOSED_CLUS);
294         selectCluSetOption(model, cluSetEditOptions, ToolsConstants.CLU_SET_CLU_SET_RANGE_FIELD, 
295                 ToolsConstants.CLU_SET_SWAP_CLU_SET_RANGE);
296         selectCluSetOption(model, cluSetEditOptions, ToolsConstants.CLU_SET_CLU_SETS_FIELD,
297                 ToolsConstants.CLU_SET_SWAP_CLU_SETS);
298     }
299     
300     private void selectCluSetOption(DataModel model, CluSetEditOptionList cluSetEditOptions,
301             String queryPath, String selectionId) {
302         final QueryPath qPath = QueryPath.parse(queryPath);
303         Data queryData = model.get(qPath);
304         if (hasData(queryPath, queryData)) {
305             cluSetEditOptions.selectItem(selectionId);
306         } else {
307             cluSetEditOptions.deSelectItem(selectionId);
308         }
309     }
310     
311     private SectionView editCluSetSection() {
312         // TODO change this to custom layoutcontroller here to support multiple model ids?
313         ModelIdPlaceHolder modelIdObj = new ModelIdPlaceHolder(CluSetsConfigurer.EDIT_CLUSET_MGT_MODEL);
314         final VerticalSectionView section = initNestedSectionView(CluSetSections.EDIT_CLU_SET, ToolsConstants.EDIT_CLU_SET, EDIT_CLUSET_MGT_MODEL);
315         VerticalSection oversight = initSection(getH3Title(""), WITH_DIVIDER);
316         Picker cluSetPicker = configureSearch(ToolsConstants.SEARCH_CLU_SET);
317         cluSetPicker.addBasicSelectionCompletedCallback(new Callback<SelectedResults>() {
318             @Override
319             public void exec(SelectedResults result) {
320                 if (result != null && result.getReturnKey() != null && result.getReturnKey().trim().length() > 0) {
321                     editSearchCluSetId = result.getReturnKey();
322                     final CluSetEditOptionList cluSetEditOptions = 
323                         cluSetEditOptionsMap.get(CluSetsConfigurer.EDIT_CLUSET_MGT_MODEL);
324                     // TODO retrieve cluset by id and
325                     final LayoutController parent = LayoutController.findParentLayout(section);
326                     if(parent != null){
327                         parent.requestModel(CluSetsConfigurer.EDIT_SEARCH_CLUSET_MGT_MODEL, new ModelRequestCallback<DataModel>() {
328                             @Override
329                             public void onModelReady(DataModel model) {
330                                 selectCluSetOptionList(model, cluSetEditOptions);
331                                 section.updateWidgetData(model);
332                             }
333 
334                             @Override
335                             public void onRequestFail(Throwable cause) {
336                                 GWT.log("Unable to retrieve model" + EDIT_SEARCH_CLUSET_MGT_MODEL.toString(), null);
337                             }
338 
339                         });
340                     }
341                 }
342             }
343         });
344         //addField(oversight, COURSE + "/" + ACADEMIC_SUBJECT_ORGS);
345         addField(modelIdObj, oversight, ToolsConstants.SEARCH_CLU_SET, generateMessageInfo("Search Clu Set"), cluSetPicker);
346         
347         section.addSection(oversight);
348         addClusetDetailsSections(section, CluSetsConfigurer.EDIT_CLUSET_MGT_MODEL);
349         return section;
350 	}
351 
352     private SectionView viewCluSetSection() {
353         final VerticalSectionView sectionView = initVerticalSectionView(CluSetSections.VIEW_CLU_SET, ToolsConstants.VIEW_CLU_SET, VIEW_CLUSET_MGT_MODEL);
354 
355 
356         Picker cluSetPicker = configureSearch(ToolsConstants.SEARCH_CLU_SET);
357         cluSetPicker.addBasicSelectionCompletedCallback(new Callback<SelectedResults>() {
358             @Override
359             public void exec(SelectedResults result) {
360                 if (result != null && result.getReturnKey() != null && result.getReturnKey().trim().length() > 0) {
361                     viewSearchCluSetId = result.getReturnKey();
362                     // TODO retrieve cluset by id and
363                     final LayoutController parent = LayoutController.findParentLayout(sectionView);
364                     if(parent != null){
365                         parent.requestModel(CluSetsConfigurer.VIEW_SEARCH_CLUSET_MGT_MODEL, new ModelRequestCallback<DataModel>() {
366                             @Override
367                             public void onModelReady(DataModel model) {
368                                 sectionView.updateWidgetData(model);
369                                 
370                                 //FIXME do something else here, rework logic
371                                 //rootSection.redraw();
372                             }
373 
374                             @Override
375                             public void onRequestFail(Throwable cause) {
376                                 GWT.log("Unable to retrieve model" + VIEW_SEARCH_CLUSET_MGT_MODEL.toString(), null);
377                             }
378 
379                         });
380                     }
381                 }
382             }
383         });
384         addField(sectionView, ToolsConstants.SEARCH_CLU_SET, generateMessageInfo(""), cluSetPicker);
385 
386         VerticalSection nameSection = initSection(null, !WITH_DIVIDER);
387         nameSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
388         addField(nameSection, ToolsConstants.CLU_SET_NAME_FIELD, generateMessageInfo(ToolsConstants.CLU_SET_NAME), new KSLabel());
389         sectionView.addSection(nameSection);
390 
391         VerticalSection descriptionSection = initSection(null, !WITH_DIVIDER);
392         descriptionSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
393         addField(descriptionSection, ToolsConstants.CLU_SET_DESCRIPTION_FIELD, generateMessageInfo("Description"), new KSLabel());
394         sectionView.addSection(descriptionSection);
395         
396         VerticalSection expirationDateSection = initSection(null, !WITH_DIVIDER);
397         expirationDateSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
398         addField(expirationDateSection, ToolsConstants.CLU_SET_EXP_DATE_FIELD, generateMessageInfo(ToolsConstants.EFFECTIVE_DATE), new KSLabel());
399         sectionView.addSection(expirationDateSection);
400         
401         VerticalSection clusSection = initSection(null, !WITH_DIVIDER);
402         clusSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
403         addField(clusSection, ToolsConstants.CLU_SET_ALL_CLUS_FIELD, 
404                 generateMessageInfo("Individual Courses"),
405                 new TranslatedStringList(ToolsConstants.CLU_SET_ALL_CLUS_FIELD));
406         sectionView.addSection(clusSection);
407         
408         VerticalSection cluSetsSection = initSection(null, !WITH_DIVIDER);
409         cluSetsSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
410         addField(cluSetsSection, ToolsConstants.CLU_SET_CLU_SETS_FIELD, 
411                 generateMessageInfo("CLU Sets"),
412                 new TranslatedStringList(ToolsConstants.CLU_SET_CLU_SETS_FIELD));
413         sectionView.addSection(cluSetsSection);
414         
415         VerticalSection cluRangeDetailsSection = initSection(null, !WITH_DIVIDER);
416         cluRangeDetailsSection.addStyleName(LUUIConstants.STYLE_BOTTOM_DIVIDER);
417         addField(cluRangeDetailsSection, ToolsConstants.CLU_SET_CLUSET_RANGE_VIEW_DETAILS_FIELD, 
418                 generateMessageInfo("Course Range"),
419                 new TranslatedStringList(ToolsConstants.CLU_SET_CLUSET_RANGE_VIEW_DETAILS_FIELD));
420         sectionView.addSection(cluRangeDetailsSection);
421 
422         return sectionView;
423     }
424 
425     private class TranslatedStringList extends DisplayMultiplicityComposite {
426         private final String parentPath;
427         public TranslatedStringList(String parentPath){
428             this.parentPath = parentPath;
429         }
430         @Override
431         public Widget createItem() {
432             String path = QueryPath.concat(parentPath, CreditCourseConstants._RUNTIME_DATA, String.valueOf(itemCount-1)).toString();
433             GroupSection ns = new GroupSection();
434             addField(ns, "id-translation", null, new KSLabel(), path);
435 
436             return ns;
437         }
438     }
439 
440     private VerticalSectionView initVerticalSectionView(Enum<?> viewEnum, String labelKey, String modelId) {
441         VerticalSectionView section = new VerticalSectionView(viewEnum, getLabel(labelKey), modelId);
442         section.addStyleName(LUUIConstants.STYLE_SECTION);
443         //section.setSectionTitle(getH1Title(labelKey));
444 
445         return section;
446     }
447 
448     private VerticalSectionView initNestedSectionView (Enum<?> viewEnum, String labelKey, String modelId) {
449         VerticalSectionView section = new VerticalSectionView(viewEnum, getLabel(labelKey), modelId);
450         section.addStyleName(LUUIConstants.STYLE_SECTION);
451         //section.setSectionTitle(getH1Title(labelKey));
452 
453         return section;
454     }
455 
456     private static VerticalSection initSection(SectionTitle title, boolean withDivider) {
457         VerticalSection section = new VerticalSection(title);
458         section.addStyleName(LUUIConstants.STYLE_SECTION);
459         if (withDivider)
460             section.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
461         return section;
462     }
463 
464     private String getLabel(String labelKey) {
465         return Application.getApplicationContext().getUILabel("clusetmanagement", "clusetmanagement", "draft", labelKey);
466     }
467 
468     private SectionTitle getH3Title(String labelKey) {
469         return SectionTitle.generateH3Title(getLabel(labelKey));
470     }
471 
472     private Picker configureSearch(String fieldKey) {
473         QueryPath path = QueryPath.concat(null, fieldKey);
474         Metadata metaData = modelDefinition.getMetadata(path);
475         Picker picker = new Picker(metaData.getInitialLookup(), metaData.getAdditionalLookups());
476         return picker;
477     }
478 
479 //    public class CourseList extends UpdatableMultiplicityComposite {
480 //        private final String parentPath;
481 //        public CourseList(String parentPath){
482 //            super(StyleType.TOP_LEVEL_GROUP);
483 //            this.parentPath = parentPath;
484 //            setAddItemLabel("Add Course");
485 ////            setItemLabel(getLabel(LUConstants.FORMAT_LABEL_KEY));
486 //        }
487 //
488 //        public Widget createItem() {
489 //            String path = QueryPath.concat(parentPath, String.valueOf(itemCount-1)).toString();
490 //            GroupSection item = new GroupSection();
491 //            addField(item, "id", "" , path);
492 //            addField(item, "name", "", path);
493 //            return item;
494 //        }
495 //    }
496 
497     public static class Picker extends KSPicker {
498 
499         private String name;
500         private LookupMetadata initLookupMetadata;
501         private List<LookupMetadata> additionalLookupMetadata;
502 
503         public Picker(LookupMetadata inLookupMetadata, List<LookupMetadata> additionalLookupMetadata) {
504             super(inLookupMetadata, additionalLookupMetadata);
505             this.initLookupMetadata = inLookupMetadata;
506             this.additionalLookupMetadata = additionalLookupMetadata;
507         }
508 
509         public String getName() {
510             return name;
511         }
512 
513         public void setName(String name) {
514             this.name = name;
515         }
516 
517         public LookupMetadata getInitLookupMetadata() {
518             return initLookupMetadata;
519         }
520 
521         public void setInitLookupMetadata(LookupMetadata initLookupMetadata) {
522             this.initLookupMetadata = initLookupMetadata;
523         }
524 
525         public List<LookupMetadata> getAdditionalLookupMetadata() {
526             return additionalLookupMetadata;
527         }
528 
529         public void setAdditionalLookupMetadata(List<LookupMetadata> additionalLookupMetadata) {
530             this.additionalLookupMetadata = additionalLookupMetadata;
531         }
532         
533     }
534     private FieldDescriptor addField(ModelIdPlaceHolder modelIdObj, Section section, String fieldKey) {
535     	return addField(modelIdObj, section, fieldKey, null, null, null);
536     }
537     private FieldDescriptor addField(ModelIdPlaceHolder modelIdObj, Section section, String fieldKey, MessageKeyInfo messageKey) {
538     	return addField(modelIdObj, section, fieldKey, messageKey, null, null);
539     }
540     private FieldDescriptor addField(ModelIdPlaceHolder modelIdObj, Section section, String fieldKey, MessageKeyInfo messageKey, Widget widget) {
541     	return addField(modelIdObj, section, fieldKey, messageKey, widget, null);
542     }
543 
544     // TODO - when DOL is pushed farther down into LOBuilder,
545     // revert these 5 methods to returning void again.
546     // TODO - when DOL is pushed farther down into LOBuilder,
547     // revert these 5 methods to returning void again.
548     protected FieldDescriptor addField(Section section, String fieldKey) {
549     	return addField(null, section, fieldKey, null, null, null);
550     }    
551     protected FieldDescriptor addField(Section section, String fieldKey, MessageKeyInfo messageKey) {
552     	return addField(null, section, fieldKey, messageKey, null, null);
553     }
554     protected FieldDescriptor addField(Section section, String fieldKey, MessageKeyInfo messageKey, Widget widget) {
555     	return addField(null, section, fieldKey, messageKey, widget, null);
556     }
557     protected FieldDescriptor addField(Section section, String fieldKey, MessageKeyInfo messageKey, String parentPath) {
558         return addField(null, section, fieldKey, messageKey, null, parentPath);
559     }
560     protected FieldDescriptor addField(Section section, String fieldKey, MessageKeyInfo messageKey, Widget widget, String parentPath) {
561         return addField(null, section, fieldKey, messageKey, widget, parentPath);
562     }
563     private FieldDescriptor addField(ModelIdPlaceHolder modelId, Section section, String fieldKey, MessageKeyInfo messageKey, Widget widget, String parentPath) {
564         QueryPath path = QueryPath.concat(parentPath, fieldKey);
565     	Metadata meta = modelDefinition.getMetadata(path);
566     	FieldDescriptor fd;
567     	if (widget != null) {
568     		fd = new FieldDescriptor(path.toString(), messageKey, meta, widget);
569     	}
570     	else{
571     		fd = new FieldDescriptor(path.toString(), messageKey, meta);
572     	}
573     	if (modelId != null) {
574     		fd.setModelId(modelId.getModelId());
575     	}
576     	section.addField(fd);
577     	return fd;
578     }
579 
580     public String getEditSearchCluSetId() {
581         return editSearchCluSetId;
582     }
583 
584     public void setEditSearchCluSetId(String searchCluSetId) {
585         this.editSearchCluSetId = searchCluSetId;
586     }
587 
588     public String getViewSearchCluSetId() {
589         return viewSearchCluSetId;
590     }
591 
592     public void setViewSearchCluSetId(String viewSearchCluSetId) {
593         this.viewSearchCluSetId = viewSearchCluSetId;
594     }
595     
596     protected MessageKeyInfo generateMessageInfo(String labelKey) {
597         return new MessageKeyInfo("clusetmanagement", "clusetmanagement", "draft", labelKey);
598     }
599     
600     class ModelIdPlaceHolder {
601     	private String modelId;
602     	
603     	public ModelIdPlaceHolder(String modelId) {
604     		setModelId(modelId);
605     	}
606     	
607 		public String getModelId() {
608 			return modelId;
609 		}
610 
611 		public void setModelId(String modelId) {
612 			this.modelId = modelId;
613 		}
614     }
615 
616     public class CluSetEditOptionList extends KSCheckBoxList{
617         public CluSetEditOptionList(){
618             SimpleListItems editOptions = new SimpleListItems();
619 
620             editOptions.addItem(ToolsConstants.CLU_SET_SWAP_APPROVED_CLUS, "Approved Courses");
621             editOptions.addItem(ToolsConstants.CLU_SET_SWAP_PROPOSED_CLUS, "Proposed Courses");
622             editOptions.addItem(ToolsConstants.CLU_SET_SWAP_CLU_SETS, "CLU Sets");
623             editOptions.addItem(ToolsConstants.CLU_SET_SWAP_CLU_SET_RANGE, "Course Ranges (Course numbers, common learning objectives, etc)");
624 
625             super.setListItems(editOptions);
626         }
627     }
628 
629 }