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