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