View Javadoc

1   package org.kuali.student.lum.lu.ui.course.client.configuration;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.HashMap;
6   import java.util.Iterator;
7   import java.util.List;
8   import java.util.Map;
9   
10  import org.kuali.student.r1.common.assembly.data.Data;
11  import org.kuali.student.r1.common.assembly.data.Data.Property;
12  import org.kuali.student.r1.common.assembly.data.Metadata;
13  import org.kuali.student.r1.common.assembly.data.QueryPath;
14  import org.kuali.student.r2.common.dto.ValidationResultInfo;
15  import org.kuali.student.r2.common.infc.ValidationResult.ErrorLevel;
16  
17  import org.kuali.student.common.ui.client.configurable.mvc.Configurer;
18  import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptorReadOnly;
19  import org.kuali.student.common.ui.client.configurable.mvc.binding.ListToTextBinding;
20  import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
21  import org.kuali.student.common.ui.client.configurable.mvc.layouts.MenuSectionController;
22  import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityConfiguration;
23  import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityFieldConfiguration;
24  import org.kuali.student.common.ui.client.configurable.mvc.sections.WarnContainer;
25  import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
26  import org.kuali.student.common.ui.client.mvc.Callback;
27  import org.kuali.student.common.ui.client.mvc.Controller;
28  import org.kuali.student.common.ui.client.mvc.DataModel;
29  import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
30  import org.kuali.student.common.ui.client.widgets.KSLabel;
31  import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
32  import org.kuali.student.common.ui.client.widgets.menus.KSListPanel;
33  import org.kuali.student.common.ui.client.widgets.table.summary.ShowRowConditionCallback;
34  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableFieldBlock;
35  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableFieldRow;
36  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableSection;
37  import org.kuali.student.core.document.ui.client.widgets.documenttool.DocumentList;
38  import org.kuali.student.core.document.ui.client.widgets.documenttool.DocumentListBinding;
39  import org.kuali.student.r1.core.statement.dto.StatementTreeViewInfo;
40  import org.kuali.student.r1.core.statement.dto.StatementTypeInfo;
41  import org.kuali.student.core.statement.ui.client.widgets.rules.SubrulePreviewWidget;
42  import org.kuali.student.core.workflow.ui.client.widgets.WorkflowEnhancedNavController;
43  import org.kuali.student.lum.common.client.lo.TreeStringBinding;
44  import org.kuali.student.lum.common.client.lu.LUUIConstants;
45  import org.kuali.student.lum.lu.assembly.data.client.constants.base.AcademicSubjectOrgInfoConstants;
46  import org.kuali.student.lum.lu.assembly.data.client.constants.base.MetaInfoConstants;
47  import org.kuali.student.lum.lu.assembly.data.client.constants.base.RichTextInfoConstants;
48  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.AffiliatedOrgInfoConstants;
49  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseActivityConstants;
50  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
51  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseDurationConstants;
52  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseExpenditureInfoConstants;
53  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseFormatConstants;
54  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseJointsConstants;
55  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseProposalConstants;
56  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseProposalInfoConstants;
57  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseRevenueInfoConstants;
58  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.FeeInfoConstants;
59  import org.kuali.student.lum.lu.assembly.data.client.constants.orch.LearningObjectiveConstants;
60  import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer.CourseSections;
61  import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer.KeyListModelWigetBinding;
62  import org.kuali.student.lum.lu.ui.course.client.configuration.ViewCourseConfigurer.ViewCourseSections;
63  import org.kuali.student.lum.lu.ui.course.client.controllers.CourseProposalController;
64  import org.kuali.student.lum.lu.ui.course.client.controllers.VersionsController;
65  import org.kuali.student.lum.lu.ui.course.client.requirements.CourseRequirementsSummaryView;
66  import org.kuali.student.lum.lu.ui.course.client.requirements.HasRequirements;
67  
68  import com.google.gwt.core.client.GWT;
69  import com.google.gwt.event.dom.client.ClickEvent;
70  import com.google.gwt.event.dom.client.ClickHandler;
71  import com.google.gwt.user.client.ui.Anchor;
72  import com.google.gwt.user.client.ui.FlowPanel;
73  import com.google.gwt.user.client.ui.HTML;
74  import com.google.gwt.user.client.ui.Widget;
75  
76  public class CourseSummaryConfigurer extends Configurer implements
77          CreditCourseProposalConstants, CreditCourseProposalInfoConstants,
78          CreditCourseConstants, CreditCourseFormatConstants,
79          CreditCourseActivityConstants, MetaInfoConstants,
80          CreditCourseDurationConstants, FeeInfoConstants,
81          LearningObjectiveConstants, AcademicSubjectOrgInfoConstants,
82          AffiliatedOrgInfoConstants, CreditCourseRevenueInfoConstants,
83          CreditCourseExpenditureInfoConstants {
84      // Override paths for course and proposal so they are root
85      public static final String PROPOSAL = "proposal";
86      public static final String COURSE = "";
87      public static final String PROPOSAL_TITLE_PATH = "proposal/name";
88  
89      protected static final String OPTIONAL = "o";
90  
91      protected List<ValidationResultInfo> validationInfos = new ArrayList<ValidationResultInfo>();
92      protected boolean showingValidation = false;
93  
94      protected List<StatementTypeInfo> stmtTypes;
95  
96      protected Controller controller;
97      protected SummaryTableSection tableSection; // review proposal data display
98      protected String modelId;
99  
100     protected List<Anchor> validateLinks = new ArrayList<Anchor>(); //KSLAB-1985
101 
102     protected class EditHandler implements ClickHandler {
103 
104         Enum<?> view;
105 
106         public EditHandler(Enum<?> view) {
107             this.view = view;
108         }
109 
110         @Override
111         public void onClick(ClickEvent event) {
112             controller.showView(view);
113         }
114     }
115     
116     public CourseSummaryConfigurer(){
117         
118     }
119 
120     public CourseSummaryConfigurer(String type, String state, String groupName,
121             DataModelDefinition modelDefinition,
122             List<StatementTypeInfo> stmtTypes, Controller controller,
123             String modelId) {
124         this.type = type;
125         this.state = state;
126         this.groupName = groupName;
127         this.modelDefinition = modelDefinition;
128         this.stmtTypes = stmtTypes;
129         this.controller = controller;
130         this.modelId = modelId;
131         tableSection = GWT.create(SummaryTableSection.class);
132         tableSection.init((Controller) controller);
133     }
134     
135     public void init(String type, String state, String groupName,
136             DataModelDefinition modelDefinition,
137             List<StatementTypeInfo> stmtTypes, Controller controller,
138             String modelId) {
139         this.type = type;
140         this.state = state;
141         this.groupName = groupName;
142         this.modelDefinition = modelDefinition;
143         this.stmtTypes = stmtTypes;
144         this.controller = controller;
145         this.modelId = modelId;
146         tableSection = GWT.create(SummaryTableSection.class);
147         tableSection.init((Controller) controller);
148     }
149 
150     protected VerticalSectionView initSectionView(Enum<?> viewEnum,
151             String labelKey) {
152         VerticalSectionView section = new VerticalSectionView(viewEnum,
153                 getLabel(labelKey), modelId);
154         section.addStyleName(LUUIConstants.STYLE_SECTION);
155         return section;
156     }
157 
158     protected SummaryTableFieldRow getFieldRow(String fieldKey,
159             MessageKeyInfo messageKey) {
160         return getFieldRow(fieldKey, messageKey, null, null, null, null, false);
161     }
162 
163     protected SummaryTableFieldRow getFieldRow(String fieldKey,
164             MessageKeyInfo messageKey, boolean optional) {
165         return getFieldRow(fieldKey, messageKey, null, null, null, null,
166                 optional);
167     }
168 
169     protected SummaryTableFieldRow getFieldRow(String fieldKey,
170             MessageKeyInfo messageKey, Widget widget, Widget widget2,
171             String parentPath, ModelWidgetBinding<?> binding, boolean optional) {
172         QueryPath path = QueryPath.concat(parentPath, fieldKey);
173         Metadata meta = modelDefinition.getMetadata(path);
174 
175         FieldDescriptorReadOnly fd = new FieldDescriptorReadOnly(
176                 path.toString(), messageKey, meta);
177         if (widget != null) {
178             fd.setFieldWidget(widget);
179         }
180         if (binding != null) {
181             fd.setWidgetBinding(binding);
182         }
183         fd.setOptional(optional);
184 
185         FieldDescriptorReadOnly fd2 = new FieldDescriptorReadOnly(
186                 path.toString(), messageKey, meta);
187         if (widget2 != null) {
188             fd2.setFieldWidget(widget2);
189         }
190         if (binding != null) {
191             fd2.setWidgetBinding(binding);
192         }
193         fd2.setOptional(optional);
194 
195         SummaryTableFieldRow fieldRow = new SummaryTableFieldRow(fd, fd2);
196 
197         return fieldRow;
198     }
199     
200     protected void addSummaryTableFieldBlocks()
201     {
202         tableSection.addSummaryTableFieldBlock(generateCourseInformationForProposal());
203         tableSection.addSummaryTableFieldBlock(generateCourseInformationForProposalCrossListed());
204         tableSection.addSummaryTableFieldBlock(generateGovernanceSection());
205         tableSection.addSummaryTableFieldBlock(generateCourseLogisticsSection());
206         tableSection.addSummaryTableFieldBlock(generateLearningObjectivesSection());
207         tableSection.addSummaryTableFieldBlock(generateRequirementsSection());
208         tableSection.addSummaryTableFieldBlock(generateActiveDatesSection());
209         tableSection.addSummaryTableFieldBlock(generateFeesSection());
210         
211     }
212 
213     public VerticalSectionView generateProposalSummarySection(boolean canEditSections) {
214         tableSection.setEditable(canEditSections);
215         addSummaryTableFieldBlocks();
216         tableSection.addSummaryTableFieldBlock(generateProposalDocumentsSection());
217 
218         if (   controller instanceof WorkflowEnhancedNavController
219             && ((WorkflowEnhancedNavController) controller).getWfUtilities() != null) {
220             final WarnContainer infoContainer1; // Header widget (with warnings if necessary)
221             final WarnContainer infoContainer2; // Footer widget (with warnings if necessary)
222             //WarnContainers initialized with buttons common to all states (error or otherwise)
223             Widget topWorkflowActionWidget= ((WorkflowEnhancedNavController) controller).getWfUtilities().getWorkflowActionsWidget();
224             Widget bottomWorkflowActionWidget = ((WorkflowEnhancedNavController) controller).getWfUtilities().getWorkflowActionsWidget();
225             
226             topWorkflowActionWidget.ensureDebugId("Top-Workflow-Actions");            
227             bottomWorkflowActionWidget.ensureDebugId("Bottom-Workflow-Actions");
228             
229             infoContainer1= generateWorkflowWidgetContainer(topWorkflowActionWidget);
230             infoContainer2= generateWorkflowWidgetContainer(bottomWorkflowActionWidget);
231 
232             ((WorkflowEnhancedNavController) controller).getWfUtilities()
233                     .addSubmitCallback(new Callback<Boolean>() {
234 
235                         @Override
236                         public void exec(Boolean result) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
237                             if (result) {
238                                 tableSection.setEditable(false);
239                                 if (controller instanceof MenuSectionController) {
240                                     ((MenuSectionController) controller).removeMenuNavigation();
241                                 }
242                             }
243 
244                         }
245                     });
246 
247             // Override beforeShow for summary section here to allow for custom validation mechanism on the table
248             VerticalSectionView verticalSection = new VerticalSectionView(CourseSections.SUMMARY, getLabel(LUUIConstants.SUMMARY_LABEL_KEY), modelId) {
249                                 
250                 @Override
251                 public void beforeShow(final Callback<Boolean> onReadyCallback) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
252 
253                     super.beforeShow(new Callback<Boolean>() {
254 
255                         @Override
256                         public void exec(final Boolean result) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
257 
258                             if (result) {
259                                 // Make sure workflow actions and status updated before showing.
260                                 ((WorkflowEnhancedNavController) controller).getWfUtilities().refresh();
261 
262                                 // Show validation errors if they exist
263                                 ((WorkflowEnhancedNavController) controller).getWfUtilities().doValidationCheck(new Callback<List<ValidationResultInfo>>() {
264                                             
265                                     @Override
266                                     public void exec(List<ValidationResultInfo> validationResults) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
267 
268                                         tableSection.enableValidation(showingValidation);   //  I think passing true here turns on all validation highlighting automatically (i.e: without requiring "click to show") 
269                                         
270                                         initializeHeaders(validationResults);
271                                         resolveMissingFieldsWarnings();
272                                         // proposal submission warnings resolution moved to overridden processValidationResults below.
273                                         
274                                         onReadyCallback.exec(result);   // calls CourseProposalController.showView.finalView 
275                                     }
276                                 });
277                             } else {
278                                 onReadyCallback.exec(result);
279                             }
280                         }
281                     });
282                 }
283                 
284                 /*
285                  * Appropriately initializes yellow warning (WarnContainers called infoContainers here) boxes at page top/bottom.
286                  */                
287                 void initializeHeaders(List<ValidationResultInfo> validationResults){                  
288                     ErrorLevel isValid = tableSection.processValidationResults(validationResults, true);                                            
289                     validationInfos = validationResults;
290                     
291                     if (isValid == ErrorLevel.OK) {
292                         
293                         infoContainer1.showWarningLayout(false);
294                         infoContainer2.showWarningLayout(false);
295                         
296                         ((WorkflowEnhancedNavController) controller).getWfUtilities().enableWorkflowActionsWidgets(true);
297                     } else { //KSLAB-1985
298 
299                         infoContainer1.clearWarnLayout();
300                         infoContainer2.clearWarnLayout();
301 
302                         infoContainer1.showWarningLayout(true);
303                         infoContainer2.showWarningLayout(true);
304                         ((WorkflowEnhancedNavController) controller).getWfUtilities().enableWorkflowActionsWidgets(false);
305                     }
306                 }
307                 
308                 /* 
309                  * Shows missing fields warnings if and their links, if appropriate. 
310                  */
311                 public void resolveMissingFieldsWarnings(){
312 
313                     if (tableSection.getIsMissingFields()) {
314                         final Anchor link1 = new Anchor("Show what's missing.");
315                         final Anchor link2 = new Anchor("Show what's missing.");                        
316                         ClickHandler showHideMsgClickHandler = new ClickHandler() {                            
317                             
318                             @Override   // Sets link action
319                             public void onClick(ClickEvent event) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
320                                 
321                                 if (!showingValidation) {
322 
323                                     for (int i = 0; i < validateLinks.size(); i++) {
324                                         
325                                         validateLinks.get(i).setText("Hide error highlighting.");
326                                     }
327                                     
328                                     showingValidation = true;
329                                     
330                                     tableSection.enableValidation(showingValidation);
331                                     tableSection.processValidationResults(validationInfos, true);
332                                 } else {
333 
334                                     for (int i = 0; i < validateLinks.size(); i++) {
335                                         
336                                         validateLinks.get(i).setText("Show what's missing.");
337                                     }
338                                     
339                                     showingValidation = false;
340                                     
341                                     tableSection.enableValidation(showingValidation);
342                                     tableSection.removeValidationHighlighting();
343                                 }
344                             }
345                         };
346                         
347                         validateLinks.add(link1);   // Enable links
348                         validateLinks.add(link2);
349 
350                         link1.addClickHandler(showHideMsgClickHandler);
351                         link2.addClickHandler(showHideMsgClickHandler);
352 
353                         infoContainer1.addWarnWidget(new KSLabel("This proposal has missing fields.  "));
354                         infoContainer1.addWarnWidget(link1);
355                         infoContainer2.addWarnWidget(new KSLabel("This proposal has missing fields.  "));
356                         infoContainer2.addWarnWidget(link2);
357                     }
358                 }
359 
360                 @Override   //overridden from BaseSection to handle conflict warnings   
361                 public ErrorLevel processValidationResults(List<ValidationResultInfo> validationResults) {                    
362 
363                     tableSection.processValidationResults(validationResults, false);
364                     resolveProposalSubmissionWarnings();
365                     
366                     return super.processValidationResults(validationResults);
367                 }
368                 
369                 /* 
370                  * Shows proposal submission warnings if appropriate.
371                  *  i.e: If conflict warnings exist 
372                  */
373                 public void resolveProposalSubmissionWarnings(){
374                     
375                     if (tableSection.getHasWarnings()) {
376 
377                         infoContainer1.addWarnWidgetBlock(new KSLabel("This proposal contains warnings that prevent it from being submitted."));
378                         infoContainer2.addWarnWidgetBlock(new KSLabel("This proposal contains warnings that prevent it from being submitted."));
379                     }
380                 }
381                
382             };
383             // Widget-adding order matters
384             verticalSection.addWidget(infoContainer1); // Header widget (with warnings if necessary)
385             verticalSection.addSection(tableSection);
386             verticalSection.addWidget(infoContainer2); // Footer widget (with warnings if necessary)
387 
388             return verticalSection;
389 
390         } else {
391 
392             VerticalSectionView verticalSection = new VerticalSectionView(
393                     CourseSections.SUMMARY,
394                     getLabel(LUUIConstants.SUMMARY_LABEL_KEY), modelId);
395             verticalSection.addSection(tableSection);
396             GWT.log("CourseSummaryConfigurer - Summary table needs a workflow controller to provide submit/validation mechanism");
397 
398             return verticalSection;
399         }
400 
401     }
402 
403     protected SummaryTableFieldBlock generateProposalDocumentsSection() {
404         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
405         block.addEditingHandler(new EditHandler(CourseSections.DOCUMENTS));
406         block.setTitle(getLabel(LUUIConstants.TOOL_DOCUMENTS_LABEL_KEY));
407         block.addSummaryTableFieldRow(getFieldRow("proposal/id",
408                 generateMessageInfo(LUUIConstants.TOOL_DOCUMENTS_LABEL_KEY),
409                 new DocumentList(LUUIConstants.REF_DOC_RELATION_PROPOSAL_TYPE,
410                         false, false), new DocumentList(
411                         LUUIConstants.REF_DOC_RELATION_PROPOSAL_TYPE, false,
412                         false), null, new DocumentListBinding("proposal/id"),
413                 false));
414         return block;
415     }
416 
417     // Initializes a WarnContainer with Action options dropdown, and Curriculum Management link 
418     protected WarnContainer generateWorkflowWidgetContainer(Widget w) {
419 
420         WarnContainer warnContainer = new WarnContainer();
421 
422         warnContainer.add(w);
423         w.addStyleName("ks-button-spacing");
424 //        warnContainer.add(new KSButton("Return to Curriculum Management",
425 //                ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
426 //
427 //                    @Override
428 //                    public void onClick(ClickEvent event) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
429 //                        Application
430 //                                .navigate(AppLocations.Locations.CURRICULUM_MANAGEMENT
431 //                                        .getLocation());
432 //                    }
433 //                }));
434 
435         // KSLAB-1985:  Warning logic/display moved to generateProposalSummarySection() where error states are established
436 
437         return warnContainer;
438     }
439 
440     public VerticalSectionView generateCourseSummarySection() {
441         tableSection.setEditable(false);
442         tableSection.addSummaryTableFieldBlock(generateCourseInformation());
443         tableSection
444                 .addSummaryTableFieldBlock(generateCourseInformationCrossListing());
445         tableSection.addSummaryTableFieldBlock(generateGovernanceSection());
446         tableSection
447                 .addSummaryTableFieldBlock(generateCourseLogisticsSection());
448         tableSection
449                 .addSummaryTableFieldBlock(generateLearningObjectivesSection());
450         tableSection.addSummaryTableFieldBlock(generateRequirementsSection());
451         tableSection.addSummaryTableFieldBlock(generateActiveDatesSection());
452         tableSection.addSummaryTableFieldBlock(generateFeesSection());
453 
454         VerticalSectionView verticalSection = new VerticalSectionView(
455                 ViewCourseSections.DETAILED,
456                 getLabel(LUUIConstants.SUMMARY_LABEL_KEY), modelId, false);
457         verticalSection.addSection(tableSection);
458 
459         return verticalSection;
460     }
461 
462     @SuppressWarnings("unchecked")
463     public SummaryTableFieldBlock generateCourseInformationForProposal() {
464         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
465         block.addEditingHandler(new EditHandler(CourseSections.COURSE_INFO));
466         block.setTitle(getLabel(LUUIConstants.INFORMATION_LABEL_KEY));
467         block.addSummaryTableFieldRow(getFieldRow(PROPOSAL_TITLE_PATH,
468                 generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY)));
469         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + COURSE_TITLE,
470                 generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY)));
471         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
472                 + TRANSCRIPT_TITLE,
473                 generateMessageInfo(LUUIConstants.SHORT_TITLE_LABEL_KEY)));
474         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + SUBJECT_AREA,
475                 generateMessageInfo(LUUIConstants.SUBJECT_CODE_LABEL_KEY)));
476         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
477                 + COURSE_NUMBER_SUFFIX,
478                 generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY)));
479         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + INSTRUCTORS,
480                 generateMessageInfo(LUUIConstants.INSTRUCTORS_LABEL_KEY), null,
481                 null, null, new KeyListModelWigetBinding("personId"), false));
482         return block;
483     }
484 
485     @SuppressWarnings("unchecked")
486     public SummaryTableFieldBlock generateCourseInformationForProposalCrossListed() {
487         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
488         block.addEditingHandler(new EditHandler(CourseSections.COURSE_INFO));
489         block.setTitle("Cross Listed Courses");
490 
491         block.addSummaryMultiplicity(getMultiplicityConfig(
492                 COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
493                 LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY, Arrays.asList(Arrays
494                         .asList(SUBJECT_AREA,
495                                 LUUIConstants.SUBJECT_CODE_LABEL_KEY), Arrays
496                         .asList(COURSE_NUMBER_SUFFIX,
497                                 LUUIConstants.COURSE_NUMBER_LABEL_KEY))));
498 
499         block.addSummaryMultiplicity(getMultiplicityConfig(
500                 COURSE + QueryPath.getPathSeparator() + JOINTS,
501                 LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
502                 Arrays.asList(Arrays.asList(
503                         CreditCourseJointsConstants.COURSE_ID,
504                         LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY))));
505 
506         block.addSummaryMultiplicity(getMultiplicityConfig(
507                 COURSE + QueryPath.getPathSeparator() + VERSIONS,
508                 LUUIConstants.VERSION_CODE_LABEL_KEY, Arrays.asList(Arrays
509                         .asList("variationCode",
510                                 LUUIConstants.VERSION_CODE_LABEL_KEY),
511                         Arrays.asList("variationTitle",
512                                 LUUIConstants.TITLE_LABEL_KEY))));
513 
514         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
515                 + PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN,
516                 generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY)));
517         block.addSummaryTableFieldRow(getFieldRow(PROPOSAL + "/" + PROPOSED_RATIONALE + "/" + RichTextInfoConstants.PLAIN,
518                 generateMessageInfo(LUUIConstants.PROPOSAL_RATIONALE_LABEL_KEY)));
519 
520         return block;
521     }
522 
523     public SummaryTableFieldBlock generateCourseInformation() {
524         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
525         block.addEditingHandler(new EditHandler(CourseSections.COURSE_INFO));
526         block.setTitle(getLabel(LUUIConstants.INFORMATION_LABEL_KEY));
527         // block.addSummaryTableFieldRow(getFieldRow(PROPOSAL_TITLE_PATH,
528         // generateMessageInfo(LUConstants.PROPOSAL_TITLE_LABEL_KEY)));
529         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + COURSE_TITLE,
530                 generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY)));
531         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
532                 + TRANSCRIPT_TITLE,
533                 generateMessageInfo(LUUIConstants.SHORT_TITLE_LABEL_KEY)));
534         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + SUBJECT_AREA,
535                 generateMessageInfo(LUUIConstants.SUBJECT_CODE_LABEL_KEY)));
536         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
537                 + COURSE_NUMBER_SUFFIX,
538                 generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY)));
539         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + INSTRUCTORS,
540                 generateMessageInfo(LUUIConstants.INSTRUCTORS_LABEL_KEY), null,
541                 null, null, new KeyListModelWigetBinding("personId"), false));
542         SummaryTableFieldBlock aRow = new SummaryTableFieldBlock();
543         aRow.setTitle("Fixing it");
544 
545         aRow.addSummaryMultiplicity(getMultiplicityConfig(
546                 COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
547                 LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY, Arrays.asList(Arrays
548                         .asList(SUBJECT_AREA,
549                                 LUUIConstants.SUBJECT_CODE_LABEL_KEY), Arrays
550                         .asList(COURSE_NUMBER_SUFFIX,
551                                 LUUIConstants.COURSE_NUMBER_LABEL_KEY))));
552 
553         block.addSummaryMultiplicity(getMultiplicityConfig(
554                 COURSE + QueryPath.getPathSeparator() + JOINTS,
555                 LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
556                 Arrays.asList(Arrays.asList(
557                         CreditCourseJointsConstants.COURSE_ID,
558                         LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY))));
559         block.addSummaryMultiplicity(getMultiplicityConfig(
560                 COURSE + QueryPath.getPathSeparator() + VERSIONS,
561                 LUUIConstants.VERSION_CODE_LABEL_KEY, Arrays.asList(Arrays
562                         .asList("variationCode",
563                                 LUUIConstants.VERSION_CODE_LABEL_KEY),
564                         Arrays.asList("variationTitle",
565                                 LUUIConstants.TITLE_LABEL_KEY))));
566 
567         // block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" +
568         // PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN,
569         // generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY)));
570 
571         return block;
572     }
573 
574     public SummaryTableFieldBlock generateCourseInformationCrossListing() {
575         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
576         block.addEditingHandler(new EditHandler(CourseSections.COURSE_INFO));
577         block.setTitle("Cross Listings");
578 
579         block.addSummaryMultiplicity(getMultiplicityConfig(
580                 COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
581                 LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY, Arrays.asList(Arrays
582                         .asList(SUBJECT_AREA,
583                                 LUUIConstants.SUBJECT_CODE_LABEL_KEY), Arrays
584                         .asList(COURSE_NUMBER_SUFFIX,
585                                 LUUIConstants.COURSE_NUMBER_LABEL_KEY))));
586 
587         block.addSummaryMultiplicity(getMultiplicityConfig(
588                 COURSE + QueryPath.getPathSeparator() + JOINTS,
589                 LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
590                 Arrays.asList(Arrays.asList(
591                         CreditCourseJointsConstants.COURSE_ID,
592                         LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY))));
593         block.addSummaryMultiplicity(getMultiplicityConfig(
594                 COURSE + QueryPath.getPathSeparator() + VERSIONS,
595                 LUUIConstants.VERSION_CODE_LABEL_KEY, Arrays.asList(Arrays
596                         .asList("variationCode",
597                                 LUUIConstants.VERSION_CODE_LABEL_KEY),
598                         Arrays.asList("variationTitle",
599                                 LUUIConstants.TITLE_LABEL_KEY))));
600 
601         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
602                 + PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN,
603                 generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY)));
604 
605         return block;
606     }
607 
608     public SummaryTableFieldBlock generateGovernanceSection() {
609         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
610         block.addEditingHandler(new EditHandler(CourseSections.GOVERNANCE));
611         block.setTitle(getLabel(LUUIConstants.GOVERNANCE_LABEL_KEY));
612         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
613                 + CAMPUS_LOCATIONS,
614                 generateMessageInfo(LUUIConstants.CAMPUS_LOCATION_LABEL_KEY)));
615         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
616                 + CURRICULUM_OVERSIGHT_ORGS_,
617                 generateMessageInfo(LUUIConstants.ACADEMIC_SUBJECT_ORGS_KEY)));
618         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + ADMIN_ORGS,
619                 generateMessageInfo(LUUIConstants.ADMIN_ORG_LABEL_KEY)));
620         return block;
621     }
622 
623     @SuppressWarnings("unchecked")
624     public SummaryTableFieldBlock generateCourseLogisticsSection() {
625         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
626         block.addEditingHandler(new EditHandler(CourseSections.COURSE_LOGISTICS));
627         block.setTitle(getLabel(LUUIConstants.LOGISTICS_LABEL_KEY));
628         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + TERMS_OFFERED,
629                 generateMessageInfo(LUUIConstants.TERMS_OFFERED_LABEL_KEY)));
630         block.addSummaryTableFieldRow(getFieldRow(
631                 COURSE + "/" + GRADING_OPTIONS,
632                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_ASSESSMENT_SCALE_LABEL_KEY)));
633         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
634                 + CreditCourseConstants.DURATION + "/" + "atpDurationTypeKey",
635                 generateMessageInfo(LUUIConstants.DURATION_TYPE_LABEL_KEY)));
636         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
637                 + CreditCourseConstants.DURATION + "/" + "timeQuantity",
638                 generateMessageInfo(LUUIConstants.DURATION_QUANTITY_LABEL_KEY)));
639         block.addSummaryTableFieldRow(getFieldRow(
640                 COURSE + "/" + PASS_FAIL,
641                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_PASS_FAIL_LABEL_KEY)));
642         block.addSummaryTableFieldRow(getFieldRow(
643                 COURSE + "/" + AUDIT,
644                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_AUDIT_LABEL_KEY)));
645 
646         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
647                 + CreditCourseConstants.FINAL_EXAM,
648                 generateMessageInfo(LUUIConstants.FINAL_EXAM_STATUS_LABEL_KEY)));
649         block.addSummaryTableFieldRow(getFieldRow(
650                 COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE,
651                 generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY),
652                 true));
653 
654         // Outcomes
655         Map<String, ModelWidgetBinding> customBindings = new HashMap<String, ModelWidgetBinding>();
656         ListToTextBinding resultValueKeysBinding = new ListToTextBinding();
657         customBindings.put("resultValueKeys", resultValueKeysBinding);
658         String outcomesKey = COURSE + QueryPath.getPathSeparator()
659                 + CREDIT_OPTIONS;
660         MultiplicityConfiguration outcomesConfig = getMultiplicityConfig(
661                 outcomesKey,
662                 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
663                 Arrays.asList(
664                         Arrays.asList(
665                                 CreditCourseConstants.TYPE,
666                                 LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY),
667                         Arrays.asList(
668                                 CREDIT_OPTION_MIN_CREDITS,
669                                 LUUIConstants.CREDIT_OPTION_MIN_CREDITS_LABEL_KEY,
670                                 OPTIONAL),
671                         Arrays.asList(
672                                 CREDIT_OPTION_MAX_CREDITS,
673                                 LUUIConstants.CREDIT_OPTION_MAX_CREDITS_LABEL_KEY,
674                                 OPTIONAL),
675                         Arrays.asList(
676                                 "resultValueKeys",
677                                 LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY,
678                                 OPTIONAL)), customBindings);
679 
680         // Massive workaround for result values problem where we dont want to
681         // show them on certain selections,
682         // in most cases you want to just use the optional flag and have it be
683         // based on empty/null data
684         // but since this data is sometimes not empty/null when we dont want to
685         // show it, it requires a show
686         // condition callback
687         tableSection.addShowRowCallback(new ShowRowConditionCallback() {
688             @Override
689             public void processShowConditions(SummaryTableFieldRow row, //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
690                     DataModel column1, DataModel column2) {
691                 if (row.getFieldDescriptor1() != null
692                         && row.getFieldDescriptor1().getFieldKey()
693                         .contains(CREDIT_OPTIONS)
694                         && (row.getFieldDescriptor1().getFieldKey()
695                         .contains("resultValueRange"))) {
696                     String type = "creditOptions/0/typeKey";
697                     Object data1 = null;
698                     Object data2 = null;
699                     if (column1 != null) {
700                         data1 = column1.get(type);
701                     }
702                     if (column2 != null) {
703                         data2 = column2.get(type);
704                     }
705 
706                     if (data1 != null && data1 instanceof String) {
707                         if (!((String) data1)
708                                 .equals("kuali.result.values.group.type.range")) {
709                             row.setShown(false);
710                         }
711                     } else if (data2 != null && data2 instanceof String) {
712                         if (!((String) data2)
713                                 .equals("kuali.result.values.group.type.range")) {
714                             row.setShown(false);
715                         }
716                     }
717                 }
718             }
719         });
720         block.addSummaryMultiplicity(outcomesConfig);
721 
722         // Formats
723         MultiplicityConfiguration formatsConfig = getMultiplicityConfig(COURSE
724                 + QueryPath.getPathSeparator() + FORMATS,
725                 LUUIConstants.FORMAT_LABEL_KEY, null);
726         MultiplicityConfiguration activitiesConfig = getMultiplicityConfig(
727                 COURSE + QueryPath.getPathSeparator() + FORMATS
728                         + QueryPath.getPathSeparator()
729                         + QueryPath.getWildCard()
730                         + QueryPath.getPathSeparator() + ACTIVITIES,
731                 LUUIConstants.ACTIVITY_LITERAL_LABEL_KEY,
732                 Arrays.asList(Arrays.asList(TYPE_KEY,
733                         LUUIConstants.ACTIVITY_TYPE_LABEL_KEY), Arrays.asList(
734                         CONTACT_HOURS + "/" + "unitQuantity",
735                         LUUIConstants.CONTACT_HOURS_LABEL_KEY), Arrays.asList(
736                         CONTACT_HOURS + "/" + "unitTypeKey",
737                         LUUIConstants.CONTACT_HOURS_FREQUENCY_LABEL_KEY),
738                         Arrays.asList(CreditCourseActivityConstants.DURATION
739                                 + "/" + "atpDurationTypeKey",
740                                 LUUIConstants.DURATION_TYPE_LABEL_KEY),
741                         Arrays.asList(CreditCourseActivityConstants.DURATION
742                                 + "/" + "timeQuantity",
743                                 LUUIConstants.DURATION_LITERAL_LABEL_KEY),
744                         Arrays.asList(DEFAULT_ENROLLMENT_ESTIMATE,
745                                 LUUIConstants.CLASS_SIZE_LABEL_KEY)));
746         formatsConfig.setNestedConfig(activitiesConfig);
747         block.addSummaryMultiplicity(formatsConfig);
748 
749         return block;
750     }
751 
752     public SummaryTableFieldBlock generateLearningObjectivesSection() {
753         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
754         block.addEditingHandler(new EditHandler(
755                 CourseSections.LEARNING_OBJECTIVES));
756         block.setTitle(getLabel(LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY));
757         SummaryTableFieldRow loRow = getFieldRow(
758                 COURSE + "/" + CreditCourseConstants.COURSE_SPECIFIC_LOS,
759                 generateMessageInfo(LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY),
760                 new KSListPanel(), new KSListPanel(), null,
761                 new TreeStringBinding(), false);
762         loRow.addContentCellStyleName("summaryTable-lo-cell");
763         block.addSummaryTableFieldRow(loRow);
764 
765         return block;
766     }
767 
768     public SummaryTableFieldBlock generateActiveDatesSection() {
769         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
770         block.addEditingHandler(new EditHandler(CourseSections.ACTIVE_DATES));
771         block.setTitle(getLabel(LUUIConstants.ACTIVE_DATES_LABEL_KEY));
772         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + START_TERM,
773                 generateMessageInfo(LUUIConstants.START_TERM_LABEL_KEY)));
774         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + END_TERM,
775                 generateMessageInfo(LUUIConstants.END_TERM_LABEL_KEY)));
776         // Probably wrong - checkbox
777         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + PILOT_COURSE,
778                 generateMessageInfo(LUUIConstants.PILOT_COURSE_LABEL_KEY)));
779         return block;
780     }
781 
782     public SummaryTableFieldBlock generateFeesSection() {
783         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
784         block.addEditingHandler(new EditHandler(CourseSections.FINANCIALS));
785         block.setTitle(getLabel(LUUIConstants.FINANCIALS_LABEL_KEY));
786         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
787                 + "feeJustification" + "/" + RichTextInfoConstants.PLAIN,
788                 generateMessageInfo(LUUIConstants.JUSTIFICATION_FEE)));
789         // Fees
790         MultiplicityConfiguration feesConfig = getMultiplicityConfig(
791                 COURSE + QueryPath.getPathSeparator() + FEES,
792                 LUUIConstants.FEE,
793                 Arrays.asList(Arrays.asList("rateType", "Rate Type"),
794                         Arrays.asList("feeType", "Fee Type")));
795         // Note the use of empty string to remove the additional row from
796         // display in the summary table
797         MultiplicityConfiguration amountsConfig = getMultiplicityConfig(
798                 COURSE + QueryPath.getPathSeparator() + FEES
799                         + QueryPath.getPathSeparator()
800                         + QueryPath.getWildCard()
801                         + QueryPath.getPathSeparator() + "feeAmounts", "",
802                 Arrays.asList(Arrays.asList("currencyQuantity", "Amount")));
803         feesConfig.setNestedConfig(amountsConfig);
804         block.addSummaryMultiplicity(feesConfig);
805 
806         // Revenue
807         MultiplicityConfiguration revenueConfig = getMultiplicityConfig(
808                 COURSE + QueryPath.getPathSeparator() + "revenues",
809                 LUUIConstants.REVENUE,
810                 Arrays.asList(Arrays.asList("affiliatedOrgs/0/orgId",
811                         "Organization"), Arrays.asList(
812                         "affiliatedOrgs/0/percentage", "Percentage")));
813         block.addSummaryMultiplicity(revenueConfig);
814 
815         // Expenditure
816         MultiplicityConfiguration expenditureConfig = getMultiplicityConfig(
817                 COURSE + QueryPath.getPathSeparator() + "expenditure"
818                         + QueryPath.getPathSeparator() + "affiliatedOrgs",
819                 LUUIConstants.EXPENDITURE,
820                 Arrays.asList(Arrays.asList("orgId", "Organization"),
821                         Arrays.asList("percentage", "Percentage")));
822         block.addSummaryMultiplicity(expenditureConfig);
823 
824         return block;
825     }
826 
827     public SummaryTableFieldBlock generateRequirementsSection() {
828 
829         final SummaryTableFieldBlock block = new SummaryTableFieldBlock();
830         block.addEditingHandler(new EditHandler(
831                 CourseSections.COURSE_REQUISITES));
832         block.setTitle(getLabel(LUUIConstants.REQUISITES_LABEL_KEY));
833 
834         // one row per requirement type
835         for (StatementTypeInfo stmtType : stmtTypes) {
836             SummaryTableFieldRow arow;
837             if (controller instanceof VersionsController
838                     || controller instanceof CourseProposalController)
839                 arow = new SummaryTableFieldRow(addRequisiteField(
840                         new FlowPanel(), stmtType), addRequisiteFieldComp(
841                         new FlowPanel(), stmtType));
842             else
843                 arow = new SummaryTableFieldRow(addRequisiteField(
844                         new FlowPanel(), stmtType), addRequisiteField(
845                         new FlowPanel(), stmtType));
846             block.addSummaryTableFieldRow(arow);
847         }
848 
849         return block;
850     }
851 
852     protected FieldDescriptorReadOnly addRequisiteField(final FlowPanel panel,
853             final StatementTypeInfo stmtType) {
854 
855         final ModelWidgetBinding<FlowPanel> widgetBinding = new ModelWidgetBinding<FlowPanel>() {
856 
857             @Override
858             public void setModelValue(FlowPanel panel, DataModel model, //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
859                     String path) {
860                 }
861 
862             @Override
863             public void setWidgetValue(final FlowPanel panel, DataModel model, //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
864                     String path) {
865                 panel.clear();
866                 if (controller instanceof HasRequirements) {
867                     final HasRequirements requirementsController = (HasRequirements) controller;
868                     if (requirementsController.getReqDataModel().isInitialized()) {
869                         List<StatementTreeViewInfo> statementTreeViewInfos = requirementsController
870                                 .getReqDataModel().getCourseReqInfo(
871                                         stmtType.getId());
872                         addSubrulePreviewWidget(panel, statementTreeViewInfos);
873                     } else {
874                         requirementsController.getReqDataModel().retrieveCourseRequirements(
875                                 AbstractCourseConfigurer.COURSE_PROPOSAL_MODEL, new Callback<Boolean>() {
876                                     @Override
877                                     public void exec(Boolean result) {
878                                         if (result) {
879                                             List<StatementTreeViewInfo> statementTreeViewInfos = requirementsController
880                                                     .getReqDataModel().getCourseReqInfo(
881                                                             stmtType.getId());
882                                             addSubrulePreviewWidget(panel, statementTreeViewInfos);
883                                             //reset initialized property so that rules load on CourseRequirementSummaryView
884                                             requirementsController.getReqDataModel().setInitialized(false);
885                                         }
886                                     }
887                                 });
888                     }
889 
890                 }
891             }
892 
893             private void addSubrulePreviewWidget(final FlowPanel panel,
894                     List<StatementTreeViewInfo> statementTreeViewInfos) {
895                 for (StatementTreeViewInfo rule : statementTreeViewInfos) {
896                     if (!rule.getStatements().isEmpty() || !rule.getReqComponents().isEmpty()) {                             
897                         SubrulePreviewWidget ruleWidget = new SubrulePreviewWidget(rule, true, CourseRequirementsSummaryView.getCluSetWidgetList(rule));
898                         panel.add(ruleWidget);
899                     }   
900                 }
901             }
902         };
903         FieldDescriptorReadOnly requisiteField = new FieldDescriptorReadOnly(
904                 COURSE + "/" + CreditCourseConstants.ID, new MessageKeyInfo(
905                         stmtType.getName()), null, panel);
906         requisiteField.setWidgetBinding(widgetBinding);
907 
908         return requisiteField;
909     }
910 
911     protected FieldDescriptorReadOnly addRequisiteFieldComp(
912             final FlowPanel panel, final StatementTypeInfo stmtType) {
913 
914         final ModelWidgetBinding<FlowPanel> widgetBinding = new ModelWidgetBinding<FlowPanel>() {
915 
916             @Override
917             public void setModelValue(FlowPanel panel, DataModel model,
918                     String path) {
919                 }
920 
921             @Override
922             public void setWidgetValue(final FlowPanel panel, DataModel model,
923                     String path) {
924                 panel.clear();
925                 List<StatementTreeViewInfo> statementTreeViewInfos = null;
926 
927                 if (controller instanceof VersionsController)
928                     statementTreeViewInfos = ((VersionsController) controller)
929                             .getReqDataModelComp().getCourseReqInfo(
930                                     stmtType.getId());
931                 else if (controller instanceof CourseProposalController)
932                     statementTreeViewInfos = ((CourseProposalController) controller)
933                             .getReqDataModelComp().getCourseReqInfo(
934                                     stmtType.getId());
935 
936                 for (StatementTreeViewInfo rule : statementTreeViewInfos) {
937                     SubrulePreviewWidget ruleWidget = new SubrulePreviewWidget(
938                             rule, true,
939                             CourseRequirementsSummaryView
940                                     .getCluSetWidgetList(rule));
941                     panel.add(ruleWidget);
942                 }
943             }
944         };
945 
946         FieldDescriptorReadOnly requisiteField = new FieldDescriptorReadOnly(
947                 COURSE + "/" + CreditCourseConstants.ID, new MessageKeyInfo(
948                         stmtType.getName()), null, panel);
949         requisiteField.setWidgetBinding(widgetBinding);
950 
951         return requisiteField;
952     }
953 
954     protected MultiplicityConfiguration getMultiplicityConfig(String path,
955             String itemLabelMessageKey, List<List<String>> fieldKeysAndLabels) {
956         return getMultiplicityConfig(path, itemLabelMessageKey,
957                 fieldKeysAndLabels, null);
958     }
959 
960     protected MultiplicityConfiguration getMultiplicityConfig(String path,
961             String itemLabelMessageKey, List<List<String>> fieldKeysAndLabels,
962             Map<String, ModelWidgetBinding> customBindings) {
963         QueryPath parentPath = QueryPath.concat(path);
964         MultiplicityConfiguration config = GWT.create(MultiplicityConfiguration.class);
965         config.init(MultiplicityConfiguration.MultiplicityType.TABLE,
966                 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
967                 modelDefinition.getMetadata(parentPath));
968         config.setItemLabel(getLabel(itemLabelMessageKey));
969         config.setUpdateable(false);
970         config.setShowHeaders(true);
971 
972         FieldDescriptorReadOnly parentFd = buildFieldDescriptor(path,
973                 getLabel(itemLabelMessageKey), null);
974         config.setParent(parentFd);
975 
976         if (fieldKeysAndLabels != null) {
977             for (List<String> fieldKeyAndLabel : fieldKeysAndLabels) {
978                 MultiplicityFieldConfiguration fd = buildMultiplicityFD(
979                         fieldKeyAndLabel.get(0), fieldKeyAndLabel.get(1),
980                         parentPath.toString());
981                 if (fieldKeyAndLabel.size() == 3
982                         && fieldKeyAndLabel.get(2).equals(OPTIONAL)) {
983                     fd.setOptional(true);
984                 }
985                 if (customBindings != null
986                         && customBindings.containsKey(fieldKeyAndLabel.get(0))) {
987                     fd.setModelWidgetBinding(customBindings
988                             .get(fieldKeyAndLabel.get(0)));
989                 }
990                 config.addFieldConfiguration(fd);
991             }
992         }
993 
994         return config;
995     }
996 
997     // TODO next 3 methods below should be moved into some kind of multiplicity
998     // helper class
999     private MultiplicityFieldConfiguration buildMultiplicityFD(String fieldKey,
1000             String labelKey, String parentPath) {
1001 
1002         QueryPath fieldPath = QueryPath.concat(parentPath,
1003                 QueryPath.getWildCard(), fieldKey);
1004         Metadata meta = modelDefinition.getMetadata(fieldPath);
1005 
1006         MultiplicityFieldConfiguration fd = new MultiplicityFieldConfiguration(
1007                 fieldPath.toString(), generateMessageInfo(labelKey), meta, null);
1008 
1009         return fd;
1010 
1011     }
1012 
1013     private FieldDescriptorReadOnly buildFieldDescriptor(String fieldKey,
1014             String messageKey, String parentPath) {
1015         return buildFieldDescriptor(fieldKey, messageKey, parentPath, null,
1016                 null);
1017     }
1018 
1019     private FieldDescriptorReadOnly buildFieldDescriptor(String fieldKey,
1020             String messageKey, String parentPath, Widget widget,
1021             ModelWidgetBinding<?> binding) {
1022 
1023         QueryPath path = QueryPath.concat(parentPath, fieldKey);
1024         Metadata meta = modelDefinition.getMetadata(path);
1025 
1026         FieldDescriptorReadOnly fd = new FieldDescriptorReadOnly(
1027                 path.toString(), generateMessageInfo(messageKey), meta);
1028         if (widget != null) {
1029             fd.setFieldWidget(widget);
1030         }
1031         if (binding != null) {
1032             fd.setWidgetBinding(binding);
1033         }
1034         return fd;
1035     }
1036 
1037     public VerticalSectionView generateCourseBriefSection() {
1038         SummaryTableSection courseBriefSection = GWT.create(SummaryTableSection.class);
1039         courseBriefSection.init(controller);
1040         courseBriefSection.setEditable(false);
1041         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
1042         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + COURSE_TITLE,
1043                 generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY)));
1044         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + "code",
1045                 generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY)));
1046         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + ADMIN_ORGS,
1047                 generateMessageInfo(LUUIConstants.ADMIN_ORG_LABEL_KEY)));
1048         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
1049                 + PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN,
1050                 generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY)));
1051         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
1052                 + CURRICULUM_OVERSIGHT_ORGS_,
1053                 generateMessageInfo(LUUIConstants.ACADEMIC_SUBJECT_ORGS_KEY)));
1054         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/"
1055                 + CAMPUS_LOCATIONS,
1056                 generateMessageInfo(LUUIConstants.CAMPUS_LOCATION_LABEL_KEY)));
1057 
1058         Map<String, ModelWidgetBinding> customBindings = new HashMap<String, ModelWidgetBinding>();
1059         ListToTextBinding resultValueKeysBinding = new ListToTextBinding();
1060         customBindings.put("resultValueKeys", resultValueKeysBinding);
1061         String outcomesKey = COURSE + QueryPath.getPathSeparator()
1062                 + CREDIT_OPTIONS;
1063         MultiplicityConfiguration outcomesConfig = getMultiplicityConfig(
1064                 outcomesKey,
1065                 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
1066                 Arrays.asList(
1067                         Arrays.asList(
1068                                 CreditCourseConstants.TYPE,
1069                                 LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY),
1070                         Arrays.asList(
1071                                 CREDIT_OPTION_MIN_CREDITS,
1072                                 LUUIConstants.CREDIT_OPTION_MIN_CREDITS_LABEL_KEY,
1073                                 OPTIONAL),
1074                         Arrays.asList(
1075                                 CREDIT_OPTION_MAX_CREDITS,
1076                                 LUUIConstants.CREDIT_OPTION_MAX_CREDITS_LABEL_KEY,
1077                                 OPTIONAL),
1078                         Arrays.asList(
1079                                 "resultValueKeys",
1080                                 LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY,
1081                                 OPTIONAL)), customBindings);
1082 
1083         // Massive workaround for result values problem where we dont want to
1084         // show them on certain selections,
1085         // in most cases you want to just use the optional flag and have it be
1086         // based on empty/null data
1087         // but since this data is sometimes not empty/null when we dont want to
1088         // show it, it requires a show
1089         // condition callback
1090         courseBriefSection.addShowRowCallback(new ShowRowConditionCallback() {
1091             @Override
1092             public void processShowConditions(SummaryTableFieldRow row,
1093                     DataModel column1, DataModel column2) {
1094                 if (row.getFieldDescriptor1() != null
1095                         && row.getFieldDescriptor1().getFieldKey()
1096                         .contains(CREDIT_OPTIONS)
1097                         && (row.getFieldDescriptor1().getFieldKey()
1098                         .contains("resultValueRange"))) {
1099                     String type = "creditOptions/0/typeKey";
1100                     Object data1 = null;
1101                     Object data2 = null;
1102                     if (column1 != null) {
1103                         data1 = column1.get(type);
1104                     }
1105                     if (column2 != null) {
1106                         data2 = column2.get(type);
1107                     }
1108 
1109                     if (data1 != null && data1 instanceof String) {
1110                         if (!((String) data1)
1111                                 .equals("kuali.result.values.group.type.range")) {
1112                             row.setShown(false);
1113                         }
1114                     } else if (data2 != null && data2 instanceof String) {
1115                         if (!((String) data2)
1116                                 .equals("kuali.result.values.group.type.range")) {
1117                             row.setShown(false);
1118                         }
1119                     }
1120                 }
1121             }
1122         });
1123         block.addSummaryMultiplicity(outcomesConfig);
1124 
1125         block.addSummaryTableFieldRow(getFieldRow(COURSE + "/" + TERMS_OFFERED,
1126                 generateMessageInfo(LUUIConstants.TERMS_OFFERED_LABEL_KEY)));
1127         block.addSummaryTableFieldRow(getFieldRow(
1128                 COURSE + "/" + GRADING_OPTIONS,
1129                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_ASSESSMENT_SCALE_LABEL_KEY)));
1130         block.addSummaryTableFieldRow(getFieldRow(
1131                 COURSE + "/" + PASS_FAIL,
1132                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_PASS_FAIL_LABEL_KEY),
1133                 true));
1134         block.addSummaryTableFieldRow(getFieldRow(
1135                 COURSE + "/" + AUDIT,
1136                 generateMessageInfo(LUUIConstants.LEARNING_RESULT_AUDIT_LABEL_KEY),
1137                 true));
1138         MultiplicityConfiguration formatsConfig = getMultiplicityConfig(COURSE
1139                 + QueryPath.getPathSeparator() + FORMATS,
1140                 LUUIConstants.FORMAT_LABEL_KEY, null);
1141         MultiplicityConfiguration activitiesConfig = getMultiplicityConfig(
1142                 COURSE + QueryPath.getPathSeparator() + FORMATS
1143                         + QueryPath.getPathSeparator()
1144                         + QueryPath.getWildCard()
1145                         + QueryPath.getPathSeparator() + ACTIVITIES,
1146                 LUUIConstants.ACTIVITY_LITERAL_LABEL_KEY, Arrays.asList(Arrays
1147                         .asList(TYPE_KEY,
1148                                 LUUIConstants.ACTIVITY_TYPE_LABEL_KEY), Arrays
1149                         .asList(CONTACT_HOURS + "/" + "unitQuantity",
1150                                 LUUIConstants.CONTACT_HOURS_LABEL_KEY), Arrays
1151                         .asList(CONTACT_HOURS + "/" + "unitTypeKey", "per"),
1152                         Arrays.asList(CreditCourseActivityConstants.DURATION
1153                                 + "/" + "atpDurationTypeKey",
1154                                 LUUIConstants.DURATION_TYPE_LABEL_KEY),
1155                         Arrays.asList(CreditCourseActivityConstants.DURATION
1156                                 + "/" + "timeQuantity",
1157                                 LUUIConstants.DURATION_LITERAL_LABEL_KEY),
1158                         Arrays.asList(DEFAULT_ENROLLMENT_ESTIMATE,
1159                                 LUUIConstants.CLASS_SIZE_LABEL_KEY)));
1160         formatsConfig.setNestedConfig(activitiesConfig);
1161         block.addSummaryMultiplicity(formatsConfig);
1162         // Fees
1163         MultiplicityConfiguration feesConfig = getMultiplicityConfig(
1164                 COURSE + QueryPath.getPathSeparator() + FEES,
1165                 LUUIConstants.FEE,
1166                 Arrays.asList(Arrays.asList("rateType", "Rate Type"),
1167                         Arrays.asList("feeType", "Fee Type")));
1168         // Note the use of empty string to remove the additional row from
1169         // display in the summary table
1170         MultiplicityConfiguration amountsConfig = getMultiplicityConfig(
1171                 COURSE + QueryPath.getPathSeparator() + FEES
1172                         + QueryPath.getPathSeparator()
1173                         + QueryPath.getWildCard()
1174                         + QueryPath.getPathSeparator() + "feeAmounts", "",
1175                 Arrays.asList(Arrays.asList("currencyQuantity", "Amount")));
1176         feesConfig.setNestedConfig(amountsConfig);
1177         block.addSummaryMultiplicity(feesConfig);
1178         /*
1179          * block.addSummaryMultiplicity(getMultiplicityConfig(COURSE +
1180          * QueryPath.getPathSeparator() + CROSS_LISTINGS,
1181          * LUConstants.CROSS_LISTED_ITEM_LABEL_KEY, Arrays.asList(
1182          * Arrays.asList(SUBJECT_AREA, LUConstants.SUBJECT_CODE_LABEL_KEY),
1183          * Arrays.asList(COURSE_NUMBER_SUFFIX,
1184          * LUConstants.COURSE_NUMBER_LABEL_KEY))));
1185          * block.addSummaryMultiplicity(getMultiplicityConfig(COURSE +
1186          * QueryPath.getPathSeparator() + JOINTS,
1187          * LUConstants.JOINT_OFFER_ITEM_LABEL_KEY, Arrays.asList(
1188          * Arrays.asList(CreditCourseJointsConstants.COURSE_ID,
1189          * LUConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY))));
1190          * block.addSummaryMultiplicity(getMultiplicityConfig(COURSE +
1191          * QueryPath.getPathSeparator() + VERSIONS,
1192          * LUConstants.VERSION_CODE_LABEL_KEY, Arrays.asList(
1193          * Arrays.asList("variationCode", LUConstants.VERSION_CODE_LABEL_KEY),
1194          * Arrays.asList("variationTitle", LUConstants.TITLE_LABEL_KEY))));
1195          */
1196         courseBriefSection.addSummaryTableFieldBlock(block);
1197         VerticalSectionView verticalSection = new VerticalSectionView(
1198                 ViewCourseSections.BRIEF, "At a Glance", modelId, false);
1199         verticalSection.addSection(courseBriefSection);
1200 
1201         return verticalSection;
1202     }
1203 
1204     public VerticalSectionView generateCourseCatalogSection() {
1205         VerticalSectionView verticalSection = new VerticalSectionView(
1206                 ViewCourseSections.CATALOG, "Catalog View", modelId, false);
1207         FieldDescriptorReadOnly catalogField = new FieldDescriptorReadOnly("",
1208                 null, null, new HTML());
1209         catalogField.hideLabel();
1210         catalogField.setWidgetBinding(new ModelWidgetBinding<HTML>() {
1211 
1212             @Override
1213             public void setModelValue(HTML widget, DataModel model, String path) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
1214                 // TODO Auto-generated method stub
1215 
1216             }
1217 
1218             @Override
1219             public void setWidgetValue(HTML widget, DataModel model, String path) { //Don't place a breakpoint here:  It will stall debugging for some unknown reason!
1220                 String code = model.get("code");
1221                 String title = model.get(COURSE + "/" + COURSE_TITLE);
1222                 String credits = "";
1223                 String outcomesKey = COURSE + QueryPath.getPathSeparator()
1224                         + CREDIT_OPTIONS;
1225                 Data outcomes = model.get(outcomesKey);
1226                 if (outcomes != null) {
1227                     Iterator<Property> iter = outcomes.realPropertyIterator();
1228                     String list = "";
1229                     ListToTextBinding binding = new ListToTextBinding();
1230                     while (iter.hasNext()) {
1231                         Property prop = iter.next();
1232                         if (prop.getKey() instanceof Integer) {
1233                             Integer number = (Integer) prop.getKey();
1234                             Object value = outcomes.get(number);
1235                             if (value instanceof Data) {
1236                                 list = list
1237                                         + binding.getStringList(model,
1238                                                 outcomesKey + "/" + number
1239                                                         + "/" + "resultValueKeys")
1240                                         + ", ";
1241                             }
1242                         }
1243                     }
1244 
1245                     if (!list.isEmpty()) {
1246                         list = list.trim();
1247                         list = list.substring(0, list.length() - 1);
1248                         credits = "(" + list + ")";
1249                     }
1250                 }
1251 
1252                 String description = model.get(COURSE + "/"
1253                         + PROPOSAL_DESCRIPTION + "/"
1254                         + RichTextInfoConstants.PLAIN);
1255                 String catalogText = "<b> " + code + " " + title + " "
1256                         + credits + "</b> " + description + " ";
1257                 catalogText.replace(" null ", "");
1258                 catalogText.trim();
1259                 widget.setHTML(catalogText);
1260 
1261             }
1262         });
1263         verticalSection.addField(catalogField);
1264 
1265         return verticalSection;
1266     }
1267 
1268     public SummaryTableSection getTableSection() {
1269         return tableSection;
1270     }
1271 }
1272 // KSLAB-1940