Clover Coverage Report - Kuali Student 1.2.1-SNAPSHOT (Aggregated)
Coverage timestamp: Wed Nov 2 2011 04:03:58 EST
../../../../../../../../../img/srcFileCovDistChart0.png 42% of files have more coverage
439   1,300   96   6.18
46   1,013   0.22   11.83
71     1.35  
6    
Warning
  • The source file used to generate this report was changed after Clover generated coverage information. The coverage reported may not match the source lines. You should regenerate the coverage information and the report to ensure the files are in sync.
 
  CourseProposalConfigurer       Line # 116 365 0% 68 442 0% 0.0
  CourseProposalConfigurer.CourseSections       Line # 133 0 - 0 0 - -1.0
  CourseProposalConfigurer.PersonList       Line # 814 8 0% 2 10 0% 0.0
  CourseProposalConfigurer.ProposerPersonList       Line # 862 2 0% 1 3 0% 0.0
  CourseProposalConfigurer.KeyListModelWigetBinding       Line # 1169 55 0% 17 84 0% 0.0
  CourseProposalConfigurer.MultiplicityFieldConfig       Line # 1264 9 0% 8 17 0% 0.0
 
No Tests
 
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    /*
17    * Copyright 2009 The Kuali Foundation Licensed under the
18    * Educational Community License, Version 2.0 (the "License"); you may
19    * not use this file except in compliance with the License. You may
20    * obtain a copy of the License at
21    *
22    * http://www.osedu.org/licenses/ECL-2.0
23    *
24    * Unless required by applicable law or agreed to in writing,
25    * software distributed under the License is distributed on an "AS IS"
26    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
27    * or implied. See the License for the specific language governing
28    * permissions and limitations under the License.
29    */
30    package org.kuali.student.lum.lu.ui.course.client.configuration;
31   
32    import java.util.ArrayList;
33    import java.util.Arrays;
34    import java.util.HashMap;
35    import java.util.List;
36    import java.util.Map;
37   
38    import org.kuali.student.common.assembly.data.Data;
39    import org.kuali.student.common.assembly.data.Data.Value;
40    import org.kuali.student.common.assembly.data.Metadata;
41    import org.kuali.student.common.assembly.data.QueryPath;
42    import org.kuali.student.common.dto.DtoConstants;
43    import org.kuali.student.common.ui.client.application.Application;
44    import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
45    import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
46    import org.kuali.student.common.ui.client.configurable.mvc.binding.HasDataValueBinding;
47    import org.kuali.student.common.ui.client.configurable.mvc.binding.ListOfStringBinding;
48    import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
49    import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
50    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.CompositeConditionOperator;
51    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityConfiguration;
52    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityFieldConfiguration;
53    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityFieldWidgetInitializer;
54    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCompositeCondition;
55    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCompositeConditionFieldConfig;
56    import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCondition;
57    import org.kuali.student.common.ui.client.configurable.mvc.sections.BaseSection;
58    import org.kuali.student.common.ui.client.configurable.mvc.sections.CollapsableSection;
59    import org.kuali.student.common.ui.client.configurable.mvc.sections.GroupSection;
60    import org.kuali.student.common.ui.client.configurable.mvc.sections.MultiplicitySection;
61    import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
62    import org.kuali.student.common.ui.client.configurable.mvc.sections.SwapEventHandler;
63    import org.kuali.student.common.ui.client.configurable.mvc.sections.SwapSection;
64    import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
65    import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
66    import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
67    import org.kuali.student.common.ui.client.mvc.Controller;
68    import org.kuali.student.common.ui.client.mvc.DataModel;
69    import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
70    import org.kuali.student.common.ui.client.mvc.HasDataValue;
71    import org.kuali.student.common.ui.client.mvc.View;
72    import org.kuali.student.common.ui.client.widgets.KSButton;
73    import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
74    import org.kuali.student.common.ui.client.widgets.KSCharCount;
75    import org.kuali.student.common.ui.client.widgets.KSCheckBox;
76    import org.kuali.student.common.ui.client.widgets.KSDropDown;
77    import org.kuali.student.common.ui.client.widgets.ListOfStringWidget;
78    import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
79    import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
80    import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayoutComponent;
81    import org.kuali.student.common.ui.client.widgets.list.KSLabelList;
82    import org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract;
83    import org.kuali.student.common.ui.client.widgets.list.KSSelectedList;
84    import org.kuali.student.common.ui.client.widgets.list.impl.SimpleListItems;
85    import org.kuali.student.common.ui.client.widgets.search.KSPicker;
86    import org.kuali.student.core.comments.ui.client.widgets.commenttool.CommentTool;
87    import org.kuali.student.core.comments.ui.client.widgets.decisiontool.DecisionPanel;
88    import org.kuali.student.core.document.ui.client.widgets.documenttool.DocumentTool;
89    import org.kuali.student.core.statement.dto.StatementTypeInfo;
90    import org.kuali.student.core.workflow.ui.client.views.CollaboratorSectionView;
91    import org.kuali.student.lum.common.client.lo.LOBuilder;
92    import org.kuali.student.lum.common.client.lo.LOBuilderBinding;
93    import org.kuali.student.lum.common.client.lo.LOPicker;
94    import org.kuali.student.lum.common.client.lo.OutlineNode;
95    import org.kuali.student.lum.common.client.lu.LUUIConstants;
96    import org.kuali.student.lum.lu.assembly.data.client.constants.base.RichTextInfoConstants;
97    import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseActivityConstants;
98    import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
99    import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseJointsConstants;
100    import org.kuali.student.lum.lu.ui.course.client.controllers.CourseProposalController;
101    import org.kuali.student.lum.lu.ui.course.client.requirements.CourseRequirementsViewController;
102   
103    import com.google.gwt.core.client.GWT;
104    import com.google.gwt.event.dom.client.ClickEvent;
105    import com.google.gwt.event.dom.client.ClickHandler;
106    import com.google.gwt.event.logical.shared.ValueChangeEvent;
107    import com.google.gwt.event.logical.shared.ValueChangeHandler;
108    import com.google.gwt.user.client.ui.Widget;
109   
110   
111    /**
112    * This is the configuration factory class for creating a proposal.
113    *
114    * @author Kuali Student Team
115    */
 
116    public class CourseProposalConfigurer extends AbstractCourseConfigurer {
117   
118    protected boolean WITH_DIVIDER = true;
119    protected boolean NO_DIVIDER = false;
120   
121    public static final String PROPOSAL_PATH = "proposal";
122    public static final String PROPOSAL_TITLE_PATH = "proposal/name";
123    public static final String COURSE_TITLE_PATH = "/courseTitle";
124   
125   
126    protected DocumentTool documentTool;
127    protected CourseSummaryConfigurer summaryConfigurer;
128   
129    protected List<StatementTypeInfo> stmtTypes;
130   
131    public static final String COURSE = "";
132   
 
133    public enum CourseSections {
134    CLU_BEGIN, PEOPLE_PERMISSONS, SUMMARY, AUTHORS_RATIONALE, GOVERNANCE, COURSE_LOGISTICS, COURSE_INFO, LEARNING_OBJECTIVES,
135    COURSE_REQUISITES, ACTIVE_DATES, FINANCIALS, ATTACHMENTS, COMMENTS,DECISIONS, DOCUMENTS,
136    PROGRAM_INFO, ASSEMBLER_TEST, WF_APPROVE_DIALOG
137    }
138   
 
139  0 toggle public void setStatementTypes(List<StatementTypeInfo> stmtTypes) {
140  0 this.stmtTypes = stmtTypes;
141    }
142   
143    /**
144    * Sets up all the views, sections, and views of the CourseProposalController. This should be called
145    * once for initialization and setup per CourseProposalController instance.
146    *
147    * @param layout
148    */
 
149  0 toggle public void configure(final CourseProposalController layout) {
150  0 type = "course";
151  0 state = DtoConstants.STATE_DRAFT;
152  0 groupName = LUUIConstants.COURSE_GROUP_NAME;
153   
154  0 if (modelDefinition.getMetadata().isCanEdit()) {
155  0 addCluStartSection(layout);
156  0 String sections = getLabel(LUUIConstants.COURSE_SECTIONS);
157   
158    //ProposalInformation
159    //layout.addSection(new String[] {editTabLabel, getLabel(LUConstants.PROPOSAL_INFORMATION_LABEL_KEY)}, generateAuthorsRationaleSection());
160   
161  0 layout.addMenu(sections);
162   
163   
164    //Course Content
165  0 layout.addMenuItem(sections, (SectionView)generateCourseInfoSection(initSectionView(CourseSections.COURSE_INFO, LUUIConstants.INFORMATION_LABEL_KEY)));
166  0 layout.addMenuItem(sections, (SectionView)generateGovernanceSection(initSectionView(CourseSections.GOVERNANCE, LUUIConstants.GOVERNANCE_LABEL_KEY)));
167  0 layout.addMenuItem(sections, (SectionView)generateCourseLogisticsSection(initSectionView(CourseSections.COURSE_LOGISTICS, LUUIConstants.LOGISTICS_LABEL_KEY)));
168  0 layout.addMenuItem(sections, generateLearningObjectivesSection());
169   
170    //Student Eligibility
171  0 layout.addMenuItem(sections, generateCourseRequisitesSection(layout,true));
172   
173    //Administrative
174  0 layout.addMenuItem(sections, (SectionView)generateActiveDatesSection(initSectionView(CourseSections.ACTIVE_DATES, LUUIConstants.ACTIVE_DATES_LABEL_KEY)));
175  0 layout.addMenuItem(sections, (SectionView)generateFinancialsSection(initSectionView(CourseSections.FINANCIALS, LUUIConstants.FINANCIALS_LABEL_KEY)));
176   
177    //Authors & Collaborators
178  0 layout.addMenuItem(sections, new CollaboratorSectionView(CourseSections.PEOPLE_PERMISSONS, LUUIConstants.SECTION_AUTHORS_AND_COLLABORATORS,COURSE_PROPOSAL_MODEL));
179   
180    //Documents
181  0 documentTool = new DocumentTool(LUUIConstants.REF_DOC_RELATION_PROPOSAL_TYPE,CourseSections.DOCUMENTS, getLabel(LUUIConstants.TOOL_DOCUMENTS_LABEL_KEY));
182  0 documentTool.setModelDefinition((DataModelDefinition)modelDefinition);
183  0 layout.addMenuItem(sections, documentTool);
184   
185    //Summary
186  0 summaryConfigurer = GWT.create(CourseSummaryConfigurer.class);
187  0 summaryConfigurer.init(type, state, groupName,(DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, COURSE_PROPOSAL_MODEL);
188  0 layout.addSpecialMenuItem(summaryConfigurer.generateProposalSummarySection(true), "Review and Submit");
189   
190    //Add common buttons to sections except for sections with specific button behavior
191  0 List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
192  0 excludedViews.add(CourseSections.DOCUMENTS);
193  0 excludedViews.add(CourseSections.COURSE_REQUISITES);
194  0 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getSaveButton(), excludedViews);
195  0 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getCancelButton(CourseSections.SUMMARY), excludedViews);
196   
197    //Specific buttons for certain views
198    //TODO people and permissions will use a different button than continue
199  0 layout.addButtonForView(CourseSections.DOCUMENTS, getContinueButton(layout));
200    }
201    else{
202  0 CourseSummaryConfigurer summaryConfigurer = GWT.create(CourseSummaryConfigurer.class);
203  0 summaryConfigurer.init(type, state, groupName, (DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, COURSE_PROPOSAL_MODEL);
204  0 layout.removeMenuNavigation();
205    layout.addView(summaryConfigurer.generateProposalSummarySection(false));
206  0 }
207  0 layout.showPrint(true);
208  0 layout.setDefaultView(CourseSections.SUMMARY);
209  0 layout.addContentWidget(layout.getWfUtilities().getProposalStatusLabel());
210  0 final CommentTool commentTool = new CommentTool(CourseSections.COMMENTS, getLabel(LUUIConstants.TOOL_COMMENTS_LABEL_KEY), "kuali.comment.type.generalRemarks", "Proposal Comments");
211    commentTool.setController(layout);
212  0
213    layout.addContentWidget(new KSButton("Comments", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
 
214  0 toggle
215    @Override
216  0 public void onClick(ClickEvent event) {
217    commentTool.show();
218    }
219    }));
220   
221  0
222  0 final DecisionPanel decisionPanel = new DecisionPanel(CourseSections.DECISIONS, getLabel(LUUIConstants.TOOL_DECISION_LABEL_KEY), "kuali.comment.type.generalRemarks");
223  0 layout.addView(decisionPanel);
224    layout.addContentWidget(new KSButton("Decisions", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
 
225  0 toggle
226    @Override
227  0 public void onClick(ClickEvent event) {
228    decisionPanel.show();
229    }
230    }));
231   
232    }
 
233  0 toggle
234  0 protected KSButton getContinueButton(final CourseProposalController layout){
 
235  0 toggle return new KSButton("Continue", new ClickHandler(){
236  0 public void onClick(ClickEvent event) {
237    layout.showNextViewOnMenu();
238    }
239    });
240    }
 
241  0 toggle
242  0 public void addCluStartSection(CourseProposalController layout) {
243  0 VerticalSectionView section = initSectionView(CourseSections.CLU_BEGIN, LUUIConstants.START_LABEL_KEY);
244  0 section.setController(layout);
245  0 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
246    addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
247    //addField(section, "proposal/rationale", generateMessageInfo(LUConstants.PROPOSAL_RATIONALE_LABEL_KEY));
248  0 //addField(section, PROPOSAL + "/" + PROPOSER_PERSON, generateMessageInfo(LUConstants.PROPOSAL_PERSON_LABEL_KEY), new PersonList()) ;
249  0 layout.addStartViewPopup(section);
250    layout.getStartPopup().setMaxHeight(600);
251    }
 
252  0 toggle
253  0 protected View generateCourseRequisitesSection(Controller layout, boolean showSaveButtons) {
254    return new CourseRequirementsViewController(layout, getLabel(LUUIConstants.REQUISITES_LABEL_KEY), CourseSections.COURSE_REQUISITES, false, showSaveButtons);
255    }
 
256  0 toggle
257    protected Section generateActiveDatesSection(Section section) {
258  0 //Add this field and hide it so it is available for cross field validation
259  0 FieldDescriptor fd = addField(section, PROPOSAL_PATH + "/" + PREV_START_TERM, generateMessageInfo(LUUIConstants.PROPOSAL_PREV_START_TERM));
260  0 fd.getFieldWidget().setVisible(false);
261    fd.hideLabel();
262  0
263    addField(section, COURSE + "/" + START_TERM, generateMessageInfo(LUUIConstants.START_TERM_LABEL_KEY));
264  0
265  0 addField(section, COURSE + "/" + PILOT_COURSE, generateMessageInfo(LUUIConstants.PILOT_COURSE_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.PILOT_COURSE_TEXT_LABEL_KEY))).setIgnoreShowRequired(true);
266    addField(section, COURSE + "/" + END_TERM, generateMessageInfo(LUUIConstants.END_TERM_LABEL_KEY)).setIgnoreShowRequired(true);
267  0
268    return section;
269    }
 
270  0 toggle
271  0 protected VerticalSection generateActiveDateEndSection() {
272  0 VerticalSection endDate = initSection(getH3Title(LUUIConstants.END_DATE_LABEL_KEY), WITH_DIVIDER);
273  0 addField(endDate, COURSE + "/" + EXPIRATION_DATE, generateMessageInfo(LUUIConstants.EXPIRATION_DATE_LABEL_KEY));
274    return endDate;
275    }
 
276  0 toggle
277  0 protected VerticalSection generateActiveDateStartSection() {
278  0 VerticalSection startDate = initSection(getH3Title(LUUIConstants.START_DATE_LABEL_KEY), WITH_DIVIDER);
279  0 addField(startDate, COURSE + "/" + CreditCourseConstants.EFFECTIVE_DATE, generateMessageInfo(LUUIConstants.EFFECTIVE_DATE_LABEL_KEY));
280    return startDate;
281    }
 
282  0 toggle
283  0 protected Section generateGovernanceSection(Section section) {
284  0 addField(section, COURSE + "/" + CAMPUS_LOCATIONS, generateMessageInfo(LUUIConstants.CAMPUS_LOCATION_LABEL_KEY));
285  0 addField(section, COURSE + "/" + CURRICULUM_OVERSIGHT_ORGS_, generateMessageInfo(LUUIConstants.ACADEMIC_SUBJECT_ORGS_KEY));
286    addField(section, COURSE + "/" + ADMIN_ORGS, generateMessageInfo(LUUIConstants.ADMIN_ORG_LABEL_KEY));
287  0
288    return section;
289    }
 
290  0 toggle
291  0 public Section generateCourseInfoSection(Section section) {
292  0 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
293  0 addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
294  0 addField(section, COURSE + "/" + TRANSCRIPT_TITLE, generateMessageInfo(LUUIConstants.SHORT_TITLE_LABEL_KEY), new KSCharCount(getMetaData(COURSE + "/" + TRANSCRIPT_TITLE)));
295  0 section.addSection(generateCourseNumberSection());
296  0 FieldDescriptor instructorsFd = addField(section, COURSE + "/" + INSTRUCTORS, generateMessageInfo(LUUIConstants.INSTRUCTORS_LABEL_KEY));
297    instructorsFd.setWidgetBinding(new KeyListModelWigetBinding("personId"));
298  0
299    section.addSection(generateDescriptionRationaleSection());
300  0
301    return section;
302    }
303   
 
304  0 toggle
305    protected GroupSection generateCourseNumberSection() {
306   
307  0 //COURSE NUMBER
308  0 GroupSection courseNumber = new GroupSection(getH4Title(""));
309  0 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION);
310  0 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
311  0 addField(courseNumber, COURSE + "/" + SUBJECT_AREA, generateMessageInfo(LUUIConstants.SUBJECT_CODE_LABEL_KEY));
312    addField(courseNumber, COURSE + "/" + COURSE_NUMBER_SUFFIX, generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY));
313    // addField(courseNumber, COURSE + "/" + SUBJECT_AREA);
314    // addField(courseNumber, COURSE + "/" + COURSE_NUMBER_SUFFIX);
315  0
316    courseNumber.addSection(generateCrossListed_Ver_Joint_Section());
317  0
318    return courseNumber;
319    }
 
320  0 toggle
321  0 protected CollapsableSection generateCrossListed_Ver_Joint_Section() {
322    CollapsableSection result = new CollapsableSection(getLabel(LUUIConstants.CL_V_J_LABEL_KEY));
323   
324    // addField(result, COURSE + "/" + CROSS_LISTINGS, null, new CrossListedList(COURSE + "/" + CROSS_LISTINGS));
325    // addField(result, COURSE + "/" + JOINTS, null, new OfferedJointlyList(COURSE + "/" + JOINTS));
326  0 // addField(result, COURSE + "/" + VERSIONS, null, new VersionCodeList(COURSE + "/" + VERSIONS));
327  0 SpanPanel crslabelpan = new SpanPanel();
328  0 crslabelpan.setStyleName("ks-multiplicity-section-label");
329  0 crslabelpan.setHTML("Cross Listed Courses");
330  0 crslabelpan.setVisible(true);
331  0 result.addWidget(crslabelpan);
332    addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
333    LUUIConstants.ADD_CROSS_LISTED_LABEL_KEY,
334    LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY,
335    Arrays.asList(
336    new MultiplicityFieldConfig(
337    SUBJECT_AREA,
338    LUUIConstants.SUBJECT_CODE_LABEL_KEY, null, null, true),
339    new MultiplicityFieldConfig(
340    COURSE_NUMBER_SUFFIX,
341    LUUIConstants.COURSE_NUMBER_LABEL_KEY, null, null, true)),
342    null,
343  0 null,0);
344  0 SpanPanel jntlabelpan = new SpanPanel();
345  0 jntlabelpan.setStyleName("ks-multiplicity-section-label");
346  0 jntlabelpan.setHTML("Jointly Offered Courses");
347  0 jntlabelpan.setVisible(true);
348  0 result.addWidget(jntlabelpan);
349    addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + JOINTS,
350    LUUIConstants.ADD_EXISTING_LABEL_KEY,
351    LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
352    Arrays.asList(
353    new MultiplicityFieldConfig(
354    CreditCourseJointsConstants.COURSE_ID,
355    LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY, null, null, true)),
356    null,
357  0 null,0);
358  0 SpanPanel vsnlabelpan = new SpanPanel();
359  0 vsnlabelpan.setStyleName("ks-multiplicity-section-label");
360  0 vsnlabelpan.setHTML("Version Codes");
361  0 vsnlabelpan.setVisible(true);
362  0 result.addWidget(vsnlabelpan);
363    addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + VERSIONS,
364    LUUIConstants.ADD_VERSION_CODE_LABEL_KEY,
365    LUUIConstants.VERSION_CODE_LABEL_KEY,
366    Arrays.asList(
367    new MultiplicityFieldConfig(
368    "variationCode",
369    LUUIConstants.VERSION_CODE_LABEL_KEY, null, null, true),
370    new MultiplicityFieldConfig(
371    "variationTitle",
372    LUUIConstants.TITLE_LABEL_KEY, null, null, true)
373    ),
374    null,
375  0 null,0);
376    return result;
377    }
 
378  0 toggle
379    protected void addFeeMultiplicityFields(Section section,
380    String path, String addItemlabelMessageKey,
381    String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
382    Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
383  0 List<String> deletionParentKeys) {
384    MultiplicityConfiguration config = setupMultiplicityConfig(
385    MultiplicityConfiguration.MultiplicityType.GROUP,
386    MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
387    path, addItemlabelMessageKey, itemLabelMessageKey,
388  0 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
389  0 MultiplicitySection ms = null;
390  0 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
391    section.addSection(ms);
392   
393    }
 
394  0 toggle
395    protected MultiplicityConfiguration setupMultiplicityConfig(
396    MultiplicityConfiguration.MultiplicityType multiplicityType,
397    MultiplicityConfiguration.StyleType styleType,
398    String path, String addItemlabelMessageKey,
399    String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
400    Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
401  0 List<String> deletionParentKeys) {
402  0 QueryPath parentPath = QueryPath.concat(path);
403    MultiplicityConfiguration config = new MultiplicityConfiguration(multiplicityType,
404  0 styleType, getMetaData(parentPath.toString()));
405  0 config.setAddItemLabel(getLabel(addItemlabelMessageKey));
406  0 config.setItemLabel(getLabel(itemLabelMessageKey));
407    config.setUpdateable(true);
408  0
409  0 FieldDescriptor parentFd = buildMultiplicityParentFieldDescriptor(path, getLabel(itemLabelMessageKey), null);
410    config.setParent(parentFd);
411  0
412  0 if (fieldConfigs != null) {
413  0 for (MultiplicityFieldConfig fieldConfig : fieldConfigs) {
414    MultiplicityFieldConfiguration fc = buildMultiplicityFD(fieldConfig.getFieldKey(),
415  0 fieldConfig.getLabelKey(), parentPath.toString());
416  0 config.addFieldConfiguration(fc);
417  0 if (fieldConfig.isNextLine()) {
418    config.nextLine();
419    }
420    }
421  0 }
422    return config;
423    }
 
424  0 toggle
425    protected MultiplicitySection addMultiplicityFields(Section section,
426    String path, String addItemlabelMessageKey,
427    String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
428    Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
429  0 List<String> deletionParentKeys,int defaultItemsCreated) {
430    MultiplicityConfiguration config = setupMultiplicityConfig(
431    MultiplicityConfiguration.MultiplicityType.GROUP,
432    MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
433    path, addItemlabelMessageKey, itemLabelMessageKey,
434  0 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
435  0 config.setDefaultItemsCreated(defaultItemsCreated);
436  0 MultiplicitySection ms = null;
437  0 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
438  0 section.addSection(ms);
439    return ms;
440    }
 
441  0 toggle
442  0 protected Metadata getMetaData(String fieldKey) {
443    return modelDefinition.getMetadata(QueryPath.concat(fieldKey));
444    }
 
445  0 toggle
446    protected MultiplicityFieldConfiguration buildMultiplicityFD(
447    String fieldKey, String labelKey, String parentPath) {
448  0
449  0 QueryPath fieldPath = QueryPath.concat(parentPath, QueryPath.getWildCard(), fieldKey);
450    Metadata meta = modelDefinition.getMetadata(fieldPath);
451  0
452    MultiplicityFieldConfiguration fd = new MultiplicityFieldConfiguration(
453    fieldPath.toString(), generateMessageInfo(labelKey), meta, null);
454   
455  0
456    return fd;
457   
458    }
 
459  0 toggle
460  0 protected FieldDescriptor buildMultiplicityParentFieldDescriptor(String fieldKey, String messageKey, String parentPath) {
461  0 QueryPath path = QueryPath.concat(parentPath, fieldKey);
462    Metadata meta = modelDefinition.getMetadata(path);
463  0
464  0 FieldDescriptor fd = new FieldDescriptor(path.toString(), generateMessageInfo(messageKey), meta);
465  0 fd.hideLabel();
466    return fd;
467    }
 
468  0 toggle
469  0 protected VerticalSection generateCourseInfoShortTitleSection() {
470  0 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
471  0 addField(shortTitle, COURSE + "/" + TRANSCRIPT_TITLE, null);
472    return shortTitle;
473    }
 
474  0 toggle
475  0 protected VerticalSection generateLongTitleSection() {
476  0 VerticalSection longTitle = initSection(getH3Title(LUUIConstants.TITLE_LABEL_KEY), WITH_DIVIDER);
477  0 addField(longTitle, COURSE + "/" + COURSE_TITLE, null);
478    return longTitle;
479    }
 
480  0 toggle
481  0 protected VerticalSection generateDescriptionRationaleSection() {
482  0 SectionTitle title = getH4Title(LUUIConstants.PROPOSAL_TITLE_SECTION_LABEL_KEY);
483  0 VerticalSection description = initSection(title, !WITH_DIVIDER);
484    title.setStyleName("cluProposalTitleSection");
485    //FIXME [KSCOR-225] Temporary fix til we have a real rich text editor
486  0 //addField(description, COURSE + "/" + DESCRIPTION, null);
487  0 addField(description, COURSE + "/" + DESCRIPTION + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY));
488    addField(description, "proposal/rationale", generateMessageInfo(LUUIConstants.PROPOSAL_RATIONALE_LABEL_KEY),
489    new KSCharCount(modelDefinition.getMetadata(QueryPath.parse("proposal/rationale"))));
490  0
491    return description;
492    }
 
493  0 toggle
494  0 public Section generateCourseLogisticsSection(Section section) {
495  0 if (section instanceof SectionView){
496    ((SectionView)section).setInstructions(getLabel(LUUIConstants.LOGISTICS_LABEL_KEY + "-instruct") + "<br><br>");
497    }
498  0
499  0 section.addSection(generateSchedulingSection());
500  0 section.addSection(generateDurationSection());
501  0 section.addSection(generateLearningResultsSection());
502    section.addSection(generateCourseFormatsSection());
503  0
504    return section;
505    }
 
506  0 toggle
507  0 protected Section generateLearningResultsSection() {
508  0 VerticalSection learningResults = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_LABEL_KEY), WITH_DIVIDER);
509    learningResults.setInstructions(getLabel(LUUIConstants.LEARNING_RESULTS_LABEL_KEY + "-instruct") + "<br><br><br>");
510  0
511  0 learningResults.addSection(generateGradesAssessmentsSection());
512  0 learningResults.addSection(generateStudentRegistrationOptionsSection());
513  0 learningResults.addSection(generateFinalExamSection());
514    learningResults.addSection(generateOutcomesSection());
515  0
516    return learningResults;
517    }
 
518  0 toggle
519    protected Section generateOutcomesSection() {
520  0
521  0 String path = COURSE + QueryPath.getPathSeparator() + CREDIT_OPTIONS;
522  0 QueryPath creditTypeFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CreditCourseConstants.TYPE);
523  0 QueryPath creditOptionFixedFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_FIXED_CREDITS);
524  0 QueryPath creditOptionMinFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MIN_CREDITS);
525  0 QueryPath creditOptionMaxFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MAX_CREDITS);
526    QueryPath creditResultValuesFullPath = QueryPath.concat(path, QueryPath.getWildCard(), "resultValues");
527  0
528  0 VerticalSection courseOutcomes = initSection(getH3Title(LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY), WITH_DIVIDER);
529    Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
530  0 new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
531    SwapCompositeCondition fixedCreditCondition = new SwapCompositeCondition(
532  0 CompositeConditionOperator.AND);
533    fixedCreditCondition.getChildrenConditions().add(
534    makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.fixed")
535  0 );
536  0 fixedCreditCondition.setConditionId("1");
537    SwapCompositeCondition multipleCreditCondition = new SwapCompositeCondition(
538  0 CompositeConditionOperator.AND);
539    multipleCreditCondition.getChildrenConditions().add(
540    makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.multiple")
541  0 );
542  0 multipleCreditCondition.setConditionId("2");
543    SwapCompositeCondition variableCreditCondition = new SwapCompositeCondition(
544  0 CompositeConditionOperator.AND);
545    variableCreditCondition.getChildrenConditions().add(
546    makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.range")
547  0 );
548    variableCreditCondition.setConditionId("3");
549  0
550    swappableFieldsDefinition.put(fixedCreditCondition,
551    Arrays.asList(
552    new SwapCompositeConditionFieldConfig(
553    new MultiplicityFieldConfiguration(
554    creditOptionFixedFullPath.toString(),
555    generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
556    modelDefinition.getMetadata(creditOptionFixedFullPath),
557    null),
558    null
559    )
560    )
561  0 );
562    MultiplicityFieldWidgetInitializer multipleCreditInitializer =
 
563  0 toggle new MultiplicityFieldWidgetInitializer() {
564    @Override
565  0 public ModelWidgetBinding<?> getModelWidgetBindingInstance() {
566    return new ListOfStringBinding();
 
567  0 toggle }
568    @Override
569  0 public Widget getNewWidget() {
570    return new ListOfStringWidget("Add Item");
571    }
572    };
573  0
574    swappableFieldsDefinition.put(multipleCreditCondition,
575    Arrays.asList(
576    new SwapCompositeConditionFieldConfig(
577    new MultiplicityFieldConfiguration(
578    creditResultValuesFullPath.toString(),
579    generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
580    modelDefinition.getMetadata(creditResultValuesFullPath),
581    multipleCreditInitializer),
582    null
583    )
584    )
585  0 );
586    swappableFieldsDefinition.put(variableCreditCondition,
587    Arrays.asList(
588    new SwapCompositeConditionFieldConfig(
589    new MultiplicityFieldConfiguration(
590    creditOptionMinFullPath.toString(),
591    generateMessageInfo(LUUIConstants.CREDIT_OPTION_MIN_CREDITS_LABEL_KEY),
592    modelDefinition.getMetadata(creditOptionMinFullPath),
593    null),
594    null
595    ),
596    new SwapCompositeConditionFieldConfig(
597    new MultiplicityFieldConfiguration(
598    creditOptionMaxFullPath.toString(),
599    generateMessageInfo(LUUIConstants.CREDIT_OPTION_MAX_CREDITS_LABEL_KEY),
600    modelDefinition.getMetadata(creditOptionMaxFullPath),
601    null),
602    null
603    )
604    )
605    );
606  0
607    MultiplicitySection ms = addMultiplicityFields(
608    courseOutcomes,
609    path,
610    LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
611    LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
612    Arrays.asList(
613    new MultiplicityFieldConfig(
614    CreditCourseConstants.TYPE,
615    LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY,
616    null, null, true)
617    ), swappableFieldsDefinition, null,1);
618  0 //Set the required panel
619  0 courseOutcomes.setRequired(ms.getConfig().getParentFd().getFieldElement().getRequiredPanel());
620    return courseOutcomes;
621   
622    }
 
623  0 toggle
624  0 protected Section generateStudentRegistrationOptionsSection() {
625    VerticalSection studentRegistrationOptionsSection = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_STUDENT_REGISTRATION_LABEL_KEY), WITH_DIVIDER);
626  0
627  0 addField(studentRegistrationOptionsSection, COURSE + "/" + AUDIT, generateMessageInfo(LUUIConstants.LEARNING_RESULT_AUDIT_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_AUDIT_TEXT_LABEL_KEY)));
628    addField(studentRegistrationOptionsSection, COURSE + "/" + PASS_FAIL, generateMessageInfo(LUUIConstants.LEARNING_RESULT_PASS_FAIL_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_PASS_FAIL_TEXT_LABEL_KEY)));
629  0
630    return studentRegistrationOptionsSection;
631    }
 
632  0 toggle
633  0 protected Section generateGradesAssessmentsSection() {
634    VerticalSection gradesAssessments = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_GRADES_ASSESSMENTS_LABEL_KEY), WITH_DIVIDER);
635  0
636    addField(gradesAssessments, COURSE + "/" + GRADING_OPTIONS, generateMessageInfo(LUUIConstants.LEARNING_RESULT_ASSESSMENT_SCALE_LABEL_KEY));
637  0
638    return gradesAssessments;
639    }
 
640  0 toggle
641    protected VerticalSection generateCourseFormatsSection() {
642  0 //COURSE FORMATS
643  0 VerticalSection courseFormats = initSection(getH3Title(LUUIConstants.FORMATS_LABEL_KEY), WITH_DIVIDER);
644  0 courseFormats.setHelp(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-help"));
645  0 courseFormats.setInstructions(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-instruct"));
646    MultiplicityConfiguration courseFormatConfig = setupMultiplicityConfig(
647    MultiplicityConfiguration.MultiplicityType.GROUP,
648    MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
649    COURSE + "/" + FORMATS, LUUIConstants.COURSE_ADD_FORMAT_LABEL_KEY,
650    LUUIConstants.FORMAT_LABEL_KEY,
651  0 null, null, null);
652  0 courseFormatConfig.setDefaultItemsCreated(1);
653    MultiplicityConfiguration activitiesConfig = setupMultiplicityConfig(
654    MultiplicityConfiguration.MultiplicityType.GROUP,
655    MultiplicityConfiguration.StyleType.SUB_LEVEL_GROUP,
656    COURSE + "/" + FORMATS + "/*/" + ACTIVITIES,
657    LUUIConstants.ADD_ACTIVITY_LABEL_KEY,
658    LUUIConstants.ACTIVITY_LITERAL_LABEL_KEY,
659    Arrays.asList(
660    new MultiplicityFieldConfig(
661    ACTIVITY_TYPE,
662    LUUIConstants.ACTIVITY_TYPE_LABEL_KEY,
663    null,
664    null,
665    true),
666    new MultiplicityFieldConfig(
667    CONTACT_HOURS + "/" + "unitQuantity",
668    LUUIConstants.CONTACT_HOURS_LABEL_KEY,
669    null,
670    null,
671    false),
672    new MultiplicityFieldConfig(
673    CONTACT_HOURS + "/" + "unitType",
674    LUUIConstants.CONTACT_HOURS_FREQUENCY_LABEL_KEY,
675    null,
676    null,
677    true),
678    new MultiplicityFieldConfig(
679    CreditCourseActivityConstants.DURATION + "/" + "atpDurationTypeKey",
680    LUUIConstants.COURSE_FORMATS_DURATION_TYPE_LABEL_KEY,
681    null,
682    null,
683    false),
684    new MultiplicityFieldConfig(
685    CreditCourseActivityConstants.DURATION + "/" + "timeQuantity",
686    LUUIConstants.DURATION_QUANTITY_LABEL_KEY,
687    null,
688    null,
689    true),
690    new MultiplicityFieldConfig(
691    DEFAULT_ENROLLMENT_ESTIMATE,
692    LUUIConstants.CLASS_SIZE_LABEL_KEY,
693    null,
694    null,
695    true)
696  0 ), null, null);
697  0 activitiesConfig.setDefaultItemsCreated(1);
698    courseFormatConfig.setNestedConfig(activitiesConfig);
699   
700  0
701  0 MultiplicitySection ms = null;
702    ms = new MultiplicitySection(courseFormatConfig,
703  0 null, null);
704  0 courseFormats.addSection(ms);
705  0 courseFormats.setRequired(courseFormatConfig.getParentFd().getFieldElement().getRequiredPanel());
706    return courseFormats;
707    }
 
708  0 toggle
709  0 protected VerticalSection generateSchedulingSection() {
710  0 VerticalSection scheduling = initSection(getH3Title(LUUIConstants.SCHEDULING_LABEL_KEY), WITH_DIVIDER);
711  0 addField(scheduling, COURSE + "/" + TERMS_OFFERED, generateMessageInfo(LUUIConstants.TERMS_OFFERED_LABEL_KEY));
712    return scheduling;
713    }
 
714  0 toggle
715  0 protected VerticalSection generateDurationSection() {
716  0 VerticalSection duration = initSection(getH3Title(LUUIConstants.DURATION_LITERAL_LABEL_KEY), WITH_DIVIDER);
717  0 duration.setInstructions(getLabel(LUUIConstants.DURATION_LITERAL_LABEL_KEY + "-instruct"));
718  0 GroupSection duration_group = new GroupSection();
719  0 addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "atpDurationTypeKey", generateMessageInfo(LUUIConstants.DURATION_TYPE_LABEL_KEY));
720    addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "timeQuantity", generateMessageInfo(LUUIConstants.DURATION_QUANTITY_LABEL_KEY));
721  0
722  0 duration.addSection(duration_group);
723    return duration;
724    }
 
725  0 toggle
726  0 protected VerticalSection generateFinalExamSection() {
727  0 VerticalSection finalExam = initSection(getH3Title(LUUIConstants.FINAL_EXAM_LABEL_KEY), WITH_DIVIDER);
728  0 GroupSection finalExam_group = new GroupSection();
729  0 GroupSection finalExamRationale_group = new GroupSection();
730    GroupSection finalExamRationale_group2 = new GroupSection();
731  0
732    FieldDescriptor field = addField(finalExam_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM, generateMessageInfo(LUUIConstants.FINAL_EXAM_STATUS_LABEL_KEY));
733  0
734  0 if (field.isVisible()){
735  0 KSSelectItemWidgetAbstract picker = (KSSelectItemWidgetAbstract) (((KSPicker) field.getFieldWidget()).getInputWidget());
736  0 final FieldDescriptor rationaleField = addField(finalExamRationale_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
737  0 rationaleField.setIgnoreShowRequired(true);
738  0 final FieldDescriptor rationaleField2 = addField(finalExamRationale_group2, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
739    rationaleField2.setIgnoreShowRequired(true);
740   
741  0 // Create SwapSection.
742  0 final String altKey = "ALT";
743  0 final String noneKey = "None";
744  0 SwapSection swapSection = new SwapSection(picker);
745  0 swapSection.addSection(finalExamRationale_group, altKey);
746  0 swapSection.addSection(finalExamRationale_group2, noneKey);
747    swapSection.setSwapEventHandler(new SwapEventHandler() {
 
748  0 toggle
749    @Override
750  0 public void onShowSwappableSection(String key, Section section) {
751    progressiveEnableAndRequireSection(true, section);
752    }
 
753  0 toggle
754    @Override
755  0 public void onRemoveSwappableSection(String key, Section section) {
756    progressiveEnableAndRequireSection(false, section);
757    }
758  0 });
759    finalExam.addSection(finalExam_group);
760  0
761  0 finalExam.addSection(swapSection);
762    return finalExam;
763  0 } else {
764    return new VerticalSection();
765    }
766   
767    }
 
768  0 toggle
769  0 private void progressiveEnableAndRequireSection(boolean enableAndRequire, Section section){
770  0 if (section != null){
771  0 List<FieldDescriptor> fields = section.getFields();
772  0 if ((fields != null) && (fields.size() > 0)){
773    BaseSection.progressiveEnableAndRequireFields(enableAndRequire, fields.toArray(new FieldDescriptor[fields.size()]));
774    }
775    }
776    }
 
777  0 toggle
778  0 protected VerticalSection generateInstructorsSection() {
779  0 VerticalSection instructors = initSection(getH3Title(LUUIConstants.INSTRUCTOR_LABEL_KEY), WITH_DIVIDER);
780  0 addField(instructors, COURSE + "/" + PRIMARY_INSTRUCTOR + "/personId");
781    return instructors;
782    }
 
783  0 toggle
784  0 protected SectionView generateLearningObjectivesSection() {
785  0 VerticalSectionView section = initSectionView(CourseSections.LEARNING_OBJECTIVES, LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY);
786  0 section.setInstructions(getLabel(LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY + "-instruct", QueryPath.concat(COURSE, COURSE_SPECIFIC_LOS, "*", "loInfo", "desc", "plain").toString()));
787  0 section.addSection(generateLearningObjectivesNestedSection());
788    return section;
789    }
 
790  0 toggle
791  0 protected VerticalSection generateLearningObjectivesNestedSection() {
792    final VerticalSection los = initSection(null, NO_DIVIDER);
793  0
794  0 QueryPath path = QueryPath.concat(COURSE, COURSE_SPECIFIC_LOS, "*", "loInfo", "desc");
795    Metadata meta = modelDefinition.getMetadata(path);
796  0
797  0 LOBuilder loBuilder = new LOBuilder(type, state, groupName, "kuali.loRepository.key.singleUse", COURSE_SPECIFIC_LOS, meta);
798    final FieldDescriptor fd = addField(los, CreditCourseConstants.COURSE_SPECIFIC_LOS, null,loBuilder, COURSE);
799  0
 
800  0 toggle loBuilder.addValueChangeHandler(new ValueChangeHandler<List<OutlineNode<LOPicker>>>(){
801    @Override
802  0 public void onValueChange(ValueChangeEvent<List<OutlineNode<LOPicker>>> event) {
803    los.setIsDirty(true);
804    }
805    });
806   
807    // have to do this here, because decision on binding is done in ks-core,
808  0 // and we obviously don't want ks-core referring to LOBuilder
809    fd.setWidgetBinding(LOBuilderBinding.INSTANCE);
810  0
811  0 los.addStyleName("KS-LUM-Section-Divider");
812    return los;
813    }
 
814   
815    public class PersonList extends KSDropDown {
816    final SimpleListItems people = new SimpleListItems();
 
817  0 toggle
818  0 public PersonList() {
819  0 final PersonList us = this;
820    final String userId = Application.getApplicationContext().getUserId();
821   
822  0 //FIXME: [KSCOR-225] Commented out search code to display drop down with only current user, and disable select
823  0 people.addItem(userId, userId);
824  0 us.setListItems(people);
825  0 us.selectItem(userId);
826  0 us.setBlankFirstItem(false);
827    this.setEnabled(false);
828   
829    /*
830    SearchRpcServiceAsync searchRpcServiceAsync = GWT.create(SearchRpcService.class);
831    SearchRequest searchRequest = new SearchRequest();
832    searchRequest.setSearchKey("person.search.personQuickViewByGivenName");
833    searchRequest.setSortColumn("person.resultColumn.GivenName");
834    searchRequest.setSortDirection(SortDirection.ASC);
835    searchRpcServiceAsync.search(searchRequest, new KSAsyncCallback<SearchResult>() {
836   
837    @Override
838    public void onSuccess(SearchResult result) {
839    for (SearchResultRow r : result.getRows()) {
840    people.addItem(r.getCells().get(0).getValue(), r.getCells().get(1).getValue());
841    }
842    us.setListItems(people);
843    us.selectItem(userId);
844    }
845   
846    @Override
847    public void handleFailure(Throwable caught) {
848    Window.alert("Unable to contact the SearchService for the list of users");
849    people.addItem(userId, userId);
850    us.setListItems(people);
851    us.selectItem(userId);
852    }
853    });
854    */
855    }
 
856  0 toggle
857    @Override
858  0 public boolean isMultipleSelect() {
859    return true;
860    }
861    }
 
862   
 
863  0 toggle public class ProposerPersonList extends KSLabelList {
864  0 public ProposerPersonList() {
865    SimpleListItems list = new SimpleListItems();
866  0
867    super.setListItems(list);
868    }
869    }
 
870  0 toggle
871  0 protected VerticalSection generateShortTitleSection() {
872  0 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
873  0 addField(shortTitle, "cluInfo/officialIdentifier/shortName", null);
874    return shortTitle;
875    }
 
876  0 toggle
877  0 protected VerticalSectionView initSectionView(Enum<?> viewEnum, String labelKey) {
878  0 VerticalSectionView section = new VerticalSectionView(viewEnum, getLabel(labelKey), COURSE_PROPOSAL_MODEL);
879  0 section.addStyleName(LUUIConstants.STYLE_SECTION);
880    return section;
881    }
882   
 
883  0 toggle
884  0 protected VerticalSection initSection(SectionTitle title, boolean withDivider) {
885  0 VerticalSection section;
886  0 if (title != null) {
887    section = new VerticalSection(title);
888  0 } else {
889    section = new VerticalSection();
890  0 }
891  0 section.addStyleName(LUUIConstants.STYLE_SECTION);
892  0 if (withDivider)
893  0 section.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
894    return section;
895    }
 
896  0 toggle
897    @Override
898  0 public MessageKeyInfo generateMessageInfo(String labelKey) {
899    return new MessageKeyInfo(groupName, type, state, labelKey);
900    }
901   
 
902  0 toggle
903    protected Section generateFinancialsSection(Section section) {
904  0
905  0 VerticalSection justiFee = initSection(getH3Title(LUUIConstants.COURSE_FEE_TITLE), WITH_DIVIDER);
906  0 SpanPanel courseFeeInstruction = new SpanPanel();
907  0 courseFeeInstruction.setStyleName("ks-form-module-elements-instruction");
908  0 courseFeeInstruction.setHTML(getLabel(LUUIConstants.COURSE_FEE_TITLE + FieldLayoutComponent.INSTRUCT_MESSAGE_KEY));
909  0 courseFeeInstruction.setVisible(true);
910    justiFee.addWidget(courseFeeInstruction);
911   
912    // addField(description, COURSE + "/" + PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUConstants.DESCRIPTION_LABEL_KEY));
913  0
914  0 addField(justiFee, COURSE + "/" + "feeJustification" + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.JUSTIFICATION_FEE));
915  0 section.addSection(justiFee);
916    Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
917    new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
918   
919    // condition:
920    // if rateType field is Variable Rate Fee
921    // if rateType field is Fixed Rate Fee
922    // if rateType field is Multiple Rate Fee
923    // if rateType field is Per Credit Fee
924  0 // String feesPathString = COURSE + QueryPath.getPathSeparator() + FEES;
925  0 QueryPath feesPath = QueryPath.concat(COURSE, FEES);
926    QueryPath rateTypeFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "rateType");
927  0 // fees/*/feeAmounts/currencyQuantity
928  0 QueryPath deletionPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "feeAmounts");
929  0 QueryPath singularFeeAmountFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "feeAmounts", "0", "currencyQuantity");
930  0 QueryPath minFeeAmountFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "feeAmounts", "0", "currencyQuantity");
931  0 QueryPath maxFeeAmountFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "feeAmounts", "1", "currencyQuantity");
932    Metadata feeAmountFieldMeta = modelDefinition.getMetadata(singularFeeAmountFieldPath);
933  0
934    SwapCompositeCondition variableRateCondition = new SwapCompositeCondition(
935  0 CompositeConditionOperator.AND);
936    variableRateCondition.getChildrenConditions().add(
937    makeCondition(rateTypeFieldPath, "Rate Type", "variableRateFee")
938  0 );
939    variableRateCondition.setConditionId("0");
940  0
941    SwapCompositeCondition fixedRateCondition = new SwapCompositeCondition(
942  0 CompositeConditionOperator.AND);
943    fixedRateCondition.getChildrenConditions().add(
944    makeCondition(rateTypeFieldPath, "Rate Type", "fixedRateFee")
945  0 );
946    fixedRateCondition.setConditionId("1");
947  0
948    SwapCompositeCondition perCreditRateCondition = new SwapCompositeCondition(
949  0 CompositeConditionOperator.AND);
950    perCreditRateCondition.getChildrenConditions().add(
951    makeCondition(rateTypeFieldPath, "Rate Type", "perCreditFee")
952  0 );
953    perCreditRateCondition.setConditionId("2");
954  0
955    SwapCompositeCondition multipleRateCondition = new SwapCompositeCondition(
956  0 CompositeConditionOperator.AND);
957    multipleRateCondition.getChildrenConditions().add(
958    makeCondition(rateTypeFieldPath, "Rate Type", "multipleRateFee")
959  0 );
960    multipleRateCondition.setConditionId("3");
961  0
962    swappableFieldsDefinition.put(variableRateCondition,
963    Arrays.asList(
964    new SwapCompositeConditionFieldConfig(
965    new MultiplicityFieldConfiguration(
966    minFeeAmountFieldPath.toString(),
967    new MessageKeyInfo("Mininum Amount"), feeAmountFieldMeta,
968    null),
969    null
970    ),
971    new SwapCompositeConditionFieldConfig(
972    new MultiplicityFieldConfiguration(
973    maxFeeAmountFieldPath.toString(),
974    new MessageKeyInfo("Maximum Amount"), feeAmountFieldMeta,
975    null),
976    null
977    ))
978    );
979  0
980    swappableFieldsDefinition.put(fixedRateCondition,
981    Arrays.asList(
982    new SwapCompositeConditionFieldConfig(
983    new MultiplicityFieldConfiguration(
984    singularFeeAmountFieldPath.toString(),
985    new MessageKeyInfo("Amount"), feeAmountFieldMeta,
986    null),
987    null))
988    );
989  0
990    swappableFieldsDefinition.put(perCreditRateCondition,
991    Arrays.asList(
992    new SwapCompositeConditionFieldConfig(
993    new MultiplicityFieldConfiguration(
994    singularFeeAmountFieldPath.toString(),
995    new MessageKeyInfo("Amount"), feeAmountFieldMeta,
996    null),
997    null))
998    );
999  0
1000    MultiplicityConfiguration multipleFeesConfig = setupMultiplicityConfig(
1001    MultiplicityConfiguration.MultiplicityType.GROUP,
1002    MultiplicityConfiguration.StyleType.BORDERLESS_TABLE,
1003    COURSE + QueryPath.getPathSeparator() + FEES + QueryPath.getPathSeparator() +
1004    QueryPath.getWildCard() + QueryPath.getPathSeparator() + "feeAmounts",
1005    LUUIConstants.ADD_ANOTHER_FEE,
1006    LUUIConstants.FEE,
1007    Arrays.asList(
1008    new MultiplicityFieldConfig(
1009    "currencyQuantity",
1010    "Amount", null, null, true)),
1011    null,
1012  0 null);
1013    swappableFieldsDefinition.put(multipleRateCondition,
1014    Arrays.asList(
1015    new SwapCompositeConditionFieldConfig(
1016    null, multipleFeesConfig
1017    ))
1018    );
1019  0
1020    addFeeMultiplicityFields(justiFee,
1021    COURSE + QueryPath.getPathSeparator() + FEES,
1022    LUUIConstants.ADD_A_FEE,
1023    LUUIConstants.FEE,
1024    Arrays.asList(
1025    new MultiplicityFieldConfig(
1026    "feeType",
1027    "Fee Type", null, null, true),
1028    new MultiplicityFieldConfig(
1029    "rateType",
1030    "Rate Type", null, null, true)),
1031    swappableFieldsDefinition,
1032    Arrays.asList(
1033    deletionPath.toString()));
1034  0
1035    section.addSection(justiFee);
1036   
1037  0
1038  0 VerticalSection financialSection = initSection(getH3Title(LUUIConstants.FINANCIAL_INFORMATION), WITH_DIVIDER);
1039  0 SpanPanel financialInfoInstruction = new SpanPanel();
1040  0 financialInfoInstruction.setStyleName("ks-form-module-elements-instruction");
1041  0 financialInfoInstruction.setHTML(getLabel(LUUIConstants.FINANCIAL_INFORMATION + FieldLayoutComponent.INSTRUCT_MESSAGE_KEY));
1042  0 financialInfoInstruction.setVisible(true);
1043  0 financialSection.addWidget(financialInfoInstruction);
1044  0 SpanPanel revenuepan = new SpanPanel();
1045  0 revenuepan.setStyleName("ks-multiplicity-section-label");
1046  0 revenuepan.setHTML("<br>Revenue");
1047  0 revenuepan.setVisible(true);
1048  0 financialSection.addWidget(revenuepan);
1049  0 setupRevenueSection(financialSection);
1050  0 SpanPanel expendpan = new SpanPanel();
1051  0 expendpan.setStyleName("ks-multiplicity-section-label");
1052  0 expendpan.setHTML("<br>Expenditures");
1053  0 expendpan.setVisible(true);
1054  0 financialSection.addWidget(expendpan);
1055  0 setupExpenditureSection(financialSection);
1056    section.addSection(financialSection);
1057  0
1058    return section;
1059    }
 
1060  0 toggle
1061    protected void setupRevenueSection(Section parentSection) {
1062  0 // TODO customize multiplicity and change "Percentage" label into LUConstants.AMOUNT
1063  0 QueryPath revenuePath = QueryPath.concat(COURSE, "revenues");
1064  0 QueryPath affiliatedOrgIdSubPath = QueryPath.concat("affiliatedOrgs", "0", "orgId");
1065  0 QueryPath percentageSubPath = QueryPath.concat("affiliatedOrgs", "0", "percentage");
1066    addMultiplicityFields(parentSection,
1067    revenuePath.toString(),
1068    LUUIConstants.ADD_ANOTHER_ORGANIZATION,
1069    LUUIConstants.REVENUE,
1070    Arrays.asList(
1071    new MultiplicityFieldConfig(
1072    affiliatedOrgIdSubPath.toString(),
1073    LUUIConstants.REVENUE, null, null, true),
1074    new MultiplicityFieldConfig(
1075    percentageSubPath.toString(),
1076    "Percentage", null, null, true)
1077    ),
1078    null,
1079    null,
1080    0);
1081    }
 
1082  0 toggle
1083    protected void setupExpenditureSection(Section parentSection) {
1084  0 // TODO customize multiplicity and change "Percentage" label into LUConstants.AMOUNT
1085  0 QueryPath expenditureAffiliatedOrgPath = QueryPath.concat(COURSE, "expenditure", "affiliatedOrgs");
1086  0 QueryPath affiliatedOrgIdSubPath = QueryPath.concat("orgId");
1087  0 QueryPath percentageSubPath = QueryPath.concat("percentage");
1088    addMultiplicityFields(parentSection,
1089    expenditureAffiliatedOrgPath.toString(),
1090    LUUIConstants.ADD_ANOTHER_ORGANIZATION,
1091    LUUIConstants.EXPENDITURE,
1092    Arrays.asList(
1093    new MultiplicityFieldConfig(
1094    affiliatedOrgIdSubPath.toString(),
1095    LUUIConstants.EXPENDITURE, null, null, true),
1096    new MultiplicityFieldConfig(
1097    percentageSubPath.toString(),
1098    "Percentage", null, null, true)
1099    ),
1100    null,
1101    null,
1102    0);
1103    }
 
1104  0 toggle
1105    protected SwapCondition makeCondition(QueryPath fieldPath, String messageLabelKey,
1106  0 String value) {
1107  0 SwapCondition swapCondition = new SwapCondition();
1108    swapCondition.setFd(new FieldDescriptor(
1109    fieldPath.toString(),
1110    new MessageKeyInfo(messageLabelKey),
1111  0 modelDefinition.getMetadata(fieldPath)));
1112  0 swapCondition.setValue(value);
1113    return swapCondition;
1114    }
1115   
 
1116  0 toggle
1117    @Override
1118  0 public String getCourseTitlePath() {
1119    return COURSE_TITLE_PATH;
1120    }
 
1121  0 toggle
1122    @Override
1123  0 public String getProposalPath() {
1124    return PROPOSAL_PATH;
1125    }
 
1126  0 toggle
1127    @Override
1128  0 public String getProposalTitlePath() {
1129    return PROPOSAL_TITLE_PATH;
1130    }
 
1131  0 toggle
1132    @Override
1133  0 public Class<? extends Enum<?>> getViewsEnum() {
1134    return CourseProposalConfigurer.CourseSections.class;
1135    }
1136   
 
1137  0 toggle
1138    @Override
1139    public String getSectionTitle(DataModel model) {
1140  0
1141  0 StringBuffer sb = new StringBuffer();
1142  0 sb.append("Modify Course: ");
1143  0 sb.append(model.get("courseCode"));
1144  0 sb.append(" - ");
1145    sb.append(model.get("transcriptTitle"));
1146  0
1147    return sb.toString();
1148    }
 
1149  0 toggle
1150    @Override
1151  0 public String getProposalHeaderTitle(DataModel model) {
1152  0 StringBuffer sb = new StringBuffer();
1153  0 if (model.get("copyOfCourseId") != null) {
1154  0 sb.append("Modify Course: ");
1155  0 sb.append(model.get("courseCode"));
1156  0 sb.append(" - ");
1157    sb.append(model.get("transcriptTitle"));
1158  0 } else {
1159  0 sb.append("New Course: ");
1160    sb.append(model.get(getCourseTitlePath()));
1161    }
1162  0
1163    return sb.toString();
1164    }
 
1165  0 toggle
1166  0 public CourseSummaryConfigurer getSummaryConfigurer() {
1167    return summaryConfigurer;
1168    }
 
1169   
1170    public static class KeyListModelWigetBinding extends ModelWidgetBindingSupport<HasDataValue> {
1171    protected String key;
1172    HasDataValueBinding hasDataValueBinding = HasDataValueBinding.INSTANCE;
 
1173  0 toggle
1174  0 public KeyListModelWigetBinding(String key) {
1175    this.key = key;
1176    }
 
1177  0 toggle
1178    @Override
1179    public void setModelValue(HasDataValue widget, DataModel model, String path) {
1180  0 // convert from the structure path/0/<id> into path/0/<key>/<id>
1181    hasDataValueBinding.setModelValue(widget, model, path);
1182  0
1183  0 QueryPath qPath = QueryPath.parse(path);
1184    Value value = ((KSSelectedList) widget).getValueWithTranslations();
1185  0
1186  0 Data idsData = null;
1187    Data idsDataStruct = null;
1188  0
1189  0 if (value != null) {
1190    idsData = value.get();
1191  0 }
1192  0 if (idsData != null) {
1193  0 for (Data.Property p : idsData) {
1194  0 if (!"_runtimeData".equals(p.getKey())) {
1195    String id = p.getValue();
1196  0 // old translation path path/_runtimeData/0/id-translation
1197  0 QueryPath translationPath = new QueryPath();
1198  0 translationPath.add(new Data.StringKey(qPath.toString()));
1199  0 translationPath.add(new Data.StringKey("_runtimeData"));
1200  0 translationPath.add(new Data.IntegerKey((Integer) p.getKey()));
1201    translationPath.add(new Data.StringKey("id-translation"));
1202  0
1203  0 Data idItem = new Data();
1204  0 String translation = model.get(translationPath.toString());
1205  0 Data idItemRuntime = new Data();
1206  0 Data idItemTranslation = new Data();
1207  0 idsDataStruct = (idsDataStruct == null) ? new Data() : idsDataStruct;
1208    idItem.set(this.key, id);
1209  0 // new translation path/0/_runtimeData/<key>/id-translation
1210  0 idItemTranslation.set("id-translation", translation);
1211  0 idItemRuntime.set(this.key, idItemTranslation);
1212  0 idItem.set("_runtimeData", idItemRuntime);
1213    idsDataStruct.add(idItem);
1214    }
1215    }
1216    }
1217  0
1218    model.set(qPath, idsDataStruct);
1219    }
 
1220  0 toggle
1221    @Override
1222  0 public void setWidgetValue(HasDataValue widget, DataModel model, String path) {
1223  0 DataModel middleManModel = new DataModel();
1224  0 if (model != null && model.getRoot() != null) {
1225    middleManModel = new DataModel(model.getDefinition(), model.getRoot().copy());
1226    }
1227  0 // convert from the structure path/0/<key>/<id> into path/0/<id>
1228  0 QueryPath qPath = QueryPath.parse(path);
1229  0 Object value = null;
1230  0 Data idsData = null;
1231  0 Data newIdsData = null;
1232    Data newIdsRuntimeData = null;
1233  0
1234  0 if (middleManModel != null) {
1235    value = middleManModel.get(qPath);
1236    }
1237  0
1238  0 if (value != null) {
1239  0 idsData = (Data) value;
1240  0 if (idsData != null) {
1241  0 for (Data.Property p : idsData) {
1242  0 if (!"_runtimeData".equals(p.getKey())) {
1243  0 Data idItem = p.getValue();
1244  0 String id = idItem.get(key);
1245    Data runtimeData = idItem.get("_runtimeData");
1246  0 // KSLAB-1790 - sometime runtimeData isn't there; no idea why
1247  0 Data translationData = null != runtimeData ? ((Data) runtimeData.get(key)) : new Data();
1248  0 newIdsData = (newIdsData == null) ? new Data() : newIdsData;
1249  0 newIdsData.add(id);
1250  0 newIdsRuntimeData = (newIdsRuntimeData == null) ? new Data() : newIdsRuntimeData;
1251    newIdsRuntimeData.add(translationData);
1252    }
1253    }
1254    }
1255  0 }
1256  0 if (newIdsData != null) {
1257  0 newIdsData.set("_runtimeData", newIdsRuntimeData);
1258  0 middleManModel.set(qPath, newIdsData);
1259    hasDataValueBinding.setWidgetValue(widget, middleManModel, path);
1260    }
1261    }
1262    }
1263   
 
1264   
1265    public static class MultiplicityFieldConfig {
1266    protected String fieldKey;
1267    protected String labelKey;
1268    boolean nextLine;
 
1269  0 toggle
1270    public MultiplicityFieldConfig() {
 
1271  0 toggle }
1272    public MultiplicityFieldConfig(String fieldKey, String labelKey,
1273  0 Widget fieldWidget, ModelWidgetBinding<?> modelWidgetBinding, boolean nextLine) {
1274  0 setFieldKey(fieldKey);
1275  0 setLabelKey(labelKey);
1276    setNextLine(nextLine);
 
1277  0 toggle }
1278  0 public String getFieldKey() {
1279    return fieldKey;
 
1280  0 toggle }
1281  0 public void setFieldKey(String fieldKey) {
1282    this.fieldKey = fieldKey;
 
1283  0 toggle }
1284  0 public String getLabelKey() {
1285    return labelKey;
 
1286  0 toggle }
1287  0 public void setLabelKey(String labelKey) {
1288    this.labelKey = labelKey;
 
1289  0 toggle }
1290  0 public boolean isNextLine() {
1291    return nextLine;
 
1292  0 toggle }
1293  0 public void setNextLine(boolean nextLine) {
1294    this.nextLine = nextLine;
1295    }
1296    }
1297    }
1298   
1299   
1300   
1301