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