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