Coverage Report - org.kuali.student.lum.lu.ui.course.client.controllers.CourseProposalController
 
Classes in this File Line Coverage Branch Coverage Complexity
CourseProposalController
0%
0/266
0%
0/128
2.179
CourseProposalController$1
0%
0/8
0%
0/6
2.179
CourseProposalController$10
0%
0/8
N/A
2.179
CourseProposalController$11
0%
0/10
N/A
2.179
CourseProposalController$11$1
0%
0/4
0%
0/2
2.179
CourseProposalController$12
0%
0/9
0%
0/2
2.179
CourseProposalController$12$1
0%
0/7
0%
0/2
2.179
CourseProposalController$12$1$1
0%
0/4
0%
0/2
2.179
CourseProposalController$13
0%
0/15
N/A
2.179
CourseProposalController$14
0%
0/16
0%
0/4
2.179
CourseProposalController$15
0%
0/17
N/A
2.179
CourseProposalController$16
0%
0/9
0%
0/2
2.179
CourseProposalController$16$1
0%
0/9
0%
0/4
2.179
CourseProposalController$17
0%
0/45
0%
0/16
2.179
CourseProposalController$18
0%
0/9
0%
0/4
2.179
CourseProposalController$18$1
0%
0/6
N/A
2.179
CourseProposalController$19
0%
0/10
0%
0/2
2.179
CourseProposalController$2
0%
0/6
0%
0/2
2.179
CourseProposalController$2$1
0%
0/6
0%
0/4
2.179
CourseProposalController$20
0%
0/7
0%
0/4
2.179
CourseProposalController$20$1
0%
0/5
0%
0/4
2.179
CourseProposalController$20$1$1
0%
0/6
N/A
2.179
CourseProposalController$21
0%
0/12
0%
0/6
2.179
CourseProposalController$21$1
0%
0/13
0%
0/4
2.179
CourseProposalController$21$1$1
0%
0/5
0%
0/2
2.179
CourseProposalController$21$1$2
0%
0/10
0%
0/2
2.179
CourseProposalController$21$2
0%
0/5
N/A
2.179
CourseProposalController$22
0%
0/3
N/A
2.179
CourseProposalController$23
0%
0/3
N/A
2.179
CourseProposalController$24
0%
0/5
0%
0/2
2.179
CourseProposalController$25
0%
0/1
N/A
2.179
CourseProposalController$3
0%
0/5
0%
0/4
2.179
CourseProposalController$4
0%
0/3
N/A
2.179
CourseProposalController$5
0%
0/4
N/A
2.179
CourseProposalController$6
0%
0/27
0%
0/18
2.179
CourseProposalController$6$1
0%
0/14
N/A
2.179
CourseProposalController$7
0%
0/3
N/A
2.179
CourseProposalController$8
0%
0/16
0%
0/10
2.179
CourseProposalController$8$1
0%
0/15
0%
0/6
2.179
CourseProposalController$9
0%
0/5
0%
0/2
2.179
 
 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  
 package org.kuali.student.lum.lu.ui.course.client.controllers;
 17  
 
 18  
 import java.text.DateFormat;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Date;
 21  
 import java.util.HashMap;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 
 25  
 import org.kuali.student.common.assembly.data.Data;
 26  
 import org.kuali.student.common.assembly.data.Metadata;
 27  
 import org.kuali.student.common.assembly.data.QueryPath;
 28  
 import org.kuali.student.common.dto.DtoConstants;
 29  
 import org.kuali.student.common.rice.StudentIdentityConstants;
 30  
 import org.kuali.student.common.rice.authorization.PermissionType;
 31  
 import org.kuali.student.common.ui.client.application.Application;
 32  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 33  
 import org.kuali.student.common.ui.client.application.ViewContext;
 34  
 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
 35  
 import org.kuali.student.common.ui.client.configurable.mvc.layouts.MenuEditableSectionController;
 36  
 import org.kuali.student.common.ui.client.configurable.mvc.sections.BaseSection;
 37  
 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
 38  
 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
 39  
 import org.kuali.student.common.ui.client.event.ActionEvent;
 40  
 import org.kuali.student.common.ui.client.event.ContentDirtyEvent;
 41  
 import org.kuali.student.common.ui.client.event.ContentDirtyEventHandler;
 42  
 import org.kuali.student.common.ui.client.event.SaveActionEvent;
 43  
 import org.kuali.student.common.ui.client.event.SaveActionHandler;
 44  
 import org.kuali.student.common.ui.client.mvc.ActionCompleteCallback;
 45  
 import org.kuali.student.common.ui.client.mvc.Callback;
 46  
 import org.kuali.student.common.ui.client.mvc.Controller;
 47  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 48  
 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
 49  
 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
 50  
 import org.kuali.student.common.ui.client.mvc.ModelProvider;
 51  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 52  
 import org.kuali.student.common.ui.client.mvc.View;
 53  
 import org.kuali.student.common.ui.client.mvc.WorkQueue;
 54  
 import org.kuali.student.common.ui.client.mvc.WorkQueue.WorkItem;
 55  
 import org.kuali.student.common.ui.client.mvc.dto.ReferenceModel;
 56  
 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
 57  
 import org.kuali.student.common.ui.client.security.AuthorizationCallback;
 58  
 import org.kuali.student.common.ui.client.security.RequiresAuthorization;
 59  
 import org.kuali.student.common.ui.client.service.BaseDataOrchestrationRpcServiceAsync;
 60  
 import org.kuali.student.common.ui.client.service.DataSaveResult;
 61  
 import org.kuali.student.common.ui.client.util.ExportElement;
 62  
 import org.kuali.student.common.ui.client.util.ExportUtils;
 63  
 import org.kuali.student.common.ui.client.util.WindowTitleUtils;
 64  
 import org.kuali.student.common.ui.client.validator.ValidatorClientUtils;
 65  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 66  
 import org.kuali.student.common.ui.client.widgets.KSCheckBox;
 67  
 import org.kuali.student.common.ui.client.widgets.KSDropDown;
 68  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 69  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
 70  
 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.YesNoCancelEnum;
 71  
 import org.kuali.student.common.ui.client.widgets.dialog.ButtonMessageDialog;
 72  
 import org.kuali.student.common.ui.client.widgets.field.layout.button.ButtonGroup;
 73  
 import org.kuali.student.common.ui.client.widgets.field.layout.button.YesNoCancelGroup;
 74  
 import org.kuali.student.common.ui.client.widgets.menus.KSMenuItemData;
 75  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
 76  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
 77  
 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
 78  
 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
 79  
 import org.kuali.student.common.ui.client.widgets.search.KSPicker;
 80  
 import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableSection;
 81  
 import org.kuali.student.common.ui.shared.IdAttributes;
 82  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 83  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 84  
 import org.kuali.student.core.statement.dto.StatementTypeInfo;
 85  
 import org.kuali.student.core.workflow.ui.client.widgets.WorkflowEnhancedNavController;
 86  
 import org.kuali.student.core.workflow.ui.client.widgets.WorkflowUtilities;
 87  
 import org.kuali.student.lum.common.client.helpers.RecentlyViewedHelper;
 88  
 import org.kuali.student.lum.common.client.lu.LUUIConstants;
 89  
 import org.kuali.student.lum.common.client.widgets.AppLocations;
 90  
 import org.kuali.student.lum.lu.LUConstants;
 91  
 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
 92  
 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer;
 93  
 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer.CourseSections;
 94  
 import org.kuali.student.lum.lu.ui.course.client.requirements.CourseRequirementsDataModel;
 95  
 import org.kuali.student.lum.lu.ui.course.client.requirements.HasRequirements;
 96  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcService;
 97  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcServiceAsync;
 98  
 import org.kuali.student.lum.lu.ui.course.client.service.CreditCourseProposalRpcService;
 99  
 import org.kuali.student.lum.lu.ui.course.client.service.CreditCourseProposalRpcServiceAsync;
 100  
 
 101  
 import com.google.gwt.core.client.GWT;
 102  
 import com.google.gwt.event.dom.client.ClickEvent;
 103  
 import com.google.gwt.event.dom.client.ClickHandler;
 104  
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 105  
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 106  
 import com.google.gwt.user.client.Window;
 107  
 import com.google.gwt.user.client.rpc.AsyncCallback;
 108  
 
 109  
 /**
 110  
  * Controller for course proposal screens.  This controller controls all functions of the course proposal process
 111  
  * and contains the data model and is responsible for retrieving its data and metadata from the server. In
 112  
  * addition, this controller is responsible for course proposal save events and updating its ui accordingly.
 113  
  * 
 114  
  *
 115  
  * @author Kuali Student Team
 116  
  *
 117  
  */
 118  
 
 119  0
 public class CourseProposalController extends MenuEditableSectionController implements RequiresAuthorization, WorkflowEnhancedNavController, HasRequirements {
 120  
 
 121  
         //RPC Services
 122  0
         protected CreditCourseProposalRpcServiceAsync cluProposalRpcServiceAsync = GWT.create(CreditCourseProposalRpcService.class);
 123  0
         protected CourseRpcServiceAsync courseServiceAsync = GWT.create(CourseRpcService.class);
 124  
         //Models
 125  0
         protected final DataModel cluProposalModel = new DataModel("Proposal");
 126  0
         protected final DataModel comparisonModel = new DataModel("Original Course");
 127  
 
 128  
         protected CourseProposalConfigurer cfg;
 129  
         
 130  
         protected WorkQueue modelRequestQueue;
 131  
 
 132  
     protected WorkflowUtilities workflowUtil;
 133  
 
 134  0
         protected boolean initialized = false;
 135  0
         protected boolean isNew = false;
 136  
 
 137  
         private static final String UPDATED_KEY = "metaInfo/updateTime";
 138  
         private static final String VERSION_KEY  = "versionInfo/versionedFromId";
 139  
     private static final String MSG_GROUP = "course";
 140  
         
 141  0
         protected String currentDocType = LUConstants.PROPOSAL_TYPE_COURSE_CREATE;
 142  0
         protected String proposalPath = "";
 143  
         protected String currentTitle;
 144  
 
 145  0
         private final DateFormat df = DateFormat.getInstance();
 146  
 
 147  0
         private final BlockingTask initializingTask = new BlockingTask("Loading");
 148  0
         protected final BlockingTask loadDataTask = new BlockingTask("Retrieving Data");
 149  0
         private final BlockingTask saving = new BlockingTask("Saving");
 150  
 
 151  
         protected CourseRequirementsDataModel reqDataModel;
 152  
         protected CourseRequirementsDataModel reqDataModelComp;
 153  
    
 154  
     public CourseProposalController(){
 155  0
         super();
 156  0
         initializeController();
 157  0
     }
 158  
 
 159  
     protected void initializeController() {
 160  0
             cfg = GWT.create(CourseProposalConfigurer.class);
 161  0
                    proposalPath = cfg.getProposalPath();
 162  0
                    workflowUtil = new WorkflowUtilities(CourseProposalController.this, proposalPath, "Proposal Actions",
 163  
                                    CourseProposalConfigurer.CourseSections.WF_APPROVE_DIALOG,"", cfg.getModelId());//TODO make msg
 164  0
                    cfg.setState(DtoConstants.STATE_DRAFT);
 165  
                    
 166  
                    //Add an extra menu item to copy the proposal to a new proposal.
 167  0
                    workflowUtil.getAdditionalItems().add(new KSMenuItemData(this.getMessage("cluCopyItem"), new ClickHandler(){
 168  
                         @Override
 169  
                         public void onClick(ClickEvent event) {
 170  0
                             if(getViewContext() != null && getViewContext().getId() != null && !getViewContext().getId().isEmpty()){
 171  0
                                     getViewContext().setId((String)cluProposalModel.get(cfg.getProposalPath()+"/id"));
 172  0
                                     getViewContext().setIdType(IdType.COPY_OF_KS_KEW_OBJECT_ID);
 173  0
                                     getViewContext().getAttributes().remove(StudentIdentityConstants.DOCUMENT_TYPE_NAME);
 174  0
                                     cluProposalModel.resetRoot(); // Reset the root so that the model can be reloaded from the copied proposal.
 175  
                         }
 176  0
                 HistoryManager.navigate("/HOME/CURRICULUM_HOME/COURSE_PROPOSAL", getViewContext());
 177  0
                         }
 178  
                 }));
 179  
                    
 180  0
                    super.setDefaultModelId(cfg.getModelId());
 181  0
                    registerModelsAndHandlers();
 182  
                    
 183  0
         addStyleName("courseProposal");
 184  
         
 185  0
         setViewContext(getViewContext());
 186  0
     }
 187  
     
 188  
     protected void registerModelsAndHandlers(){
 189  0
         reqDataModel = new CourseRequirementsDataModel(this);
 190  0
         reqDataModelComp = new CourseRequirementsDataModel(this);
 191  
             
 192  0
         super.registerModel(super.getDefaultModelId(), new ModelProvider<DataModel>() {
 193  
 
 194  
             @Override
 195  
             public void requestModel(final ModelRequestCallback<DataModel> callback) {
 196  0
                 if (modelRequestQueue == null){
 197  0
                     modelRequestQueue = new WorkQueue();
 198  
                 }
 199  
 
 200  0
                 WorkItem workItem = new WorkItem(){
 201  
                     @Override
 202  
                     public void exec(Callback<Boolean> workCompleteCallback) {
 203  0
                         if (cluProposalModel.getRoot() == null || initialized == false){
 204  0
                             populateModel(callback, workCompleteCallback);
 205  
                         } else {
 206  0
                             callback.onModelReady(cluProposalModel);
 207  0
                             workCompleteCallback.exec(true);
 208  
                         }
 209  0
                     }
 210  
                 };
 211  0
                 modelRequestQueue.submit(workItem);
 212  
 
 213  0
             }
 214  
 
 215  
         });
 216  0
         super.registerModel("ComparisonModel", new ModelProvider<DataModel>() {
 217  
             @Override
 218  
             public void requestModel(final ModelRequestCallback<DataModel> callback) {
 219  0
                     if(comparisonModel.getRoot() != null && comparisonModel.getRoot().size() != 0){
 220  0
                             callback.onModelReady(comparisonModel);
 221  
                             
 222  
                     }
 223  
                     else{
 224  0
                             callback.onModelReady(null);
 225  
                     }
 226  
                 
 227  0
             }
 228  
         });
 229  0
         super.addApplicationEventHandler(ContentDirtyEvent.TYPE, new ContentDirtyEventHandler(){
 230  
                         public void onContentDirty(ContentDirtyEvent event) {
 231  0
                         setContentWarning("You have unsaved changes");                                
 232  0
                         }                
 233  
         });
 234  
 
 235  0
         super.addApplicationEventHandler(SaveActionEvent.TYPE, new SaveActionHandler(){
 236  
             public void doSave(SaveActionEvent saveAction) {
 237  0
                 GWT.log("CluProposalController received save action request.", null);
 238  0
                 doSaveAction(saveAction);
 239  0
             }
 240  
         }); 
 241  0
             }
 242  
     
 243  
     /**
 244  
      * Used to populate the proposal model based on the view context.  
 245  
      * 
 246  
      * @param callback
 247  
      * @param workCompleteCallback
 248  
      */
 249  
     protected void populateModel(final ModelRequestCallback<DataModel> callback, Callback<Boolean> workCompleteCallback){
 250  0
             if(getViewContext().getIdType() == IdType.DOCUMENT_ID){
 251  0
             getCluProposalFromWorkflowId(callback, workCompleteCallback);
 252  0
         } else if (getViewContext().getIdType() == IdType.KS_KEW_OBJECT_ID || getViewContext().getIdType() == IdType.OBJECT_ID){
 253  
                 // Admin Retire and Loading an approved Proposal go here
 254  0
             getCluProposalFromProposalId(getViewContext().getId(), callback, workCompleteCallback);
 255  0
         } else if (getViewContext().getIdType() == IdType.COPY_OF_OBJECT_ID){
 256  0
                 if(LUConstants.PROPOSAL_TYPE_COURSE_MODIFY.equals(getViewContext().getAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME))||
 257  
                                LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN.equals(getViewContext().getAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME))){
 258  0
                         createModifyCluProposalModel("versionComment", callback, workCompleteCallback);
 259  
                 }else{
 260  0
                         createCopyCourseModel(getViewContext().getId(), callback, workCompleteCallback);
 261  
                 }
 262  0
         } else if (getViewContext().getIdType() == IdType.COPY_OF_KS_KEW_OBJECT_ID){
 263  
                 // Copy to New Proposal Button goes here.
 264  0
                 createCopyCourseProposalModel(getViewContext().getId(), callback, workCompleteCallback);
 265  
         } else{
 266  0
             createNewCluProposalModel(callback, workCompleteCallback);
 267  
         }
 268  0
     }
 269  
 
 270  
     protected void getCurrentModel(final ModelRequestCallback<DataModel> callback, Callback<Boolean> workCompleteCallback){
 271  0
             if (cluProposalModel.getRoot() != null && cluProposalModel.getRoot().size() > 0){
 272  0
                 String id = cluProposalModel.get(cfg.getProposalPath()+"/id");
 273  0
                 if(id != null){
 274  0
                         getCluProposalFromProposalId(id, callback, workCompleteCallback);
 275  
                 }
 276  
                 else{
 277  0
                         populateModel(callback, workCompleteCallback);
 278  
                 }
 279  0
             }
 280  
             else{
 281  0
                     populateModel(callback, workCompleteCallback);
 282  
             }
 283  0
     }
 284  
 
 285  
     private void intializeView(final Callback<Boolean> onReadyCallback) {
 286  0
             if (initialized) {
 287  0
                     onReadyCallback.exec(true);
 288  
             } else {
 289  0
                     initialized = true;
 290  0
                     KSBlockingProgressIndicator.addTask(initializingTask);
 291  0
                     setContentWarning("");
 292  0
             this.requestModel(new ModelRequestCallback<DataModel>(){
 293  
 
 294  
                                 @Override
 295  
                                 public void onModelReady(DataModel model) {
 296  
                                         
 297  
                                         //Setup View Context & determine id type
 298  0
                                         String idType = null;
 299  0
                                     String viewContextId = "";
 300  0
                                     if(getViewContext().getIdType() != null){
 301  0
                                 idType = getViewContext().getIdType().toString();
 302  0
                                 viewContextId = getViewContext().getId();
 303  0
                                 if(getViewContext().getIdType()==IdAttributes.IdType.COPY_OF_OBJECT_ID){
 304  0
                                         viewContextId = null;
 305  
                                 }
 306  
 
 307  
                                     }
 308  
 
 309  
                                     //  Change to Modify if we're coming in as create (not retire or other future doctypes)
 310  
                                     //  and the version_key has a value
 311  0
                                     if ((currentDocType.equals(LUConstants.PROPOSAL_TYPE_COURSE_CREATE)) && 
 312  
                                                     (cluProposalModel.get(VERSION_KEY) != null) && (!(cluProposalModel.get(VERSION_KEY).equals(""))))
 313  
                                     {
 314  0
                                             currentDocType = LUConstants.PROPOSAL_TYPE_COURSE_MODIFY;
 315  
                                     }
 316  
                                     //Check for admin modify type
 317  0
                                     if(LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN.equals(cluProposalModel.get(cfg.getProposalPath()+"/type"))){
 318  0
                                             currentDocType = LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN;
 319  
                                     }
 320  
                                     
 321  
                                     //Get the state for save action
 322  0
                                     String dtoState = getStateforSaveAction(cluProposalModel); 
 323  
                                     
 324  
                                     //Get the current workflow node for proposal
 325  0
                                     String workflowNode = cluProposalModel.get(cfg.getProposalPath()+"/workflowNode");
 326  
                                     
 327  
                                     //Add properties to an id attributes map so metadata service can get correct metadata
 328  0
                                         HashMap<String, String> idAttributes = new HashMap<String, String>();
 329  0
                                     if(idType != null){
 330  0
                                             idAttributes.put(IdAttributes.ID_TYPE, idType);
 331  
                                     }
 332  0
                                     idAttributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, currentDocType);                                                                        
 333  0
                                     idAttributes.put(DtoConstants.DTO_STATE, dtoState);                                    
 334  0
                                     idAttributes.put(DtoConstants.DTO_NEXT_STATE, cfg.getNextState());
 335  0
                                     if (LUConstants.PROPOSAL_TYPE_COURSE_MODIFY.equalsIgnoreCase(currentDocType) ||
 336  
                                             LUConstants.PROPOSAL_TYPE_COURSE_CREATE.equals(currentDocType)){                                            
 337  0
                                             idAttributes.put(DtoConstants.DTO_WORKFLOW_NODE, workflowNode);
 338  
                                     }
 339  
 
 340  
                                     
 341  
                                     //Get metadata and complete initializing the screen
 342  0
                                     getCourseProposalRpcService().getMetadata(viewContextId, idAttributes, new KSAsyncCallback<Metadata>(){
 343  
                                                 @Override
 344  
                         public void handleTimeout(Throwable caught) {
 345  0
                                         initializeFailed(); 
 346  0
                                                 }
 347  
 
 348  
                                                 @Override
 349  
                         public void handleFailure(Throwable caught) {
 350  0
                                                         initializeFailed();
 351  0
                                     throw new RuntimeException("Failed to get model definition.", caught);
 352  
                                 }
 353  
 
 354  
                                                 public void initializeFailed(){
 355  0
                                                 initialized = false;
 356  0
                                         onReadyCallback.exec(false);
 357  0
                                         KSBlockingProgressIndicator.removeTask(initializingTask);                                                        
 358  0
                                                 }
 359  
                                                 
 360  
                                 public void onSuccess(Metadata result) {
 361  0
                                         DataModelDefinition def = new DataModelDefinition(result);
 362  0
                                     cluProposalModel.setDefinition(def);
 363  0
                                     comparisonModel.setDefinition(def);
 364  
 
 365  0
                                     configureScreens(def, onReadyCallback);
 366  
 
 367  0
                                 }
 368  
                                   });
 369  
                                         
 370  0
                                 }
 371  
 
 372  
                                 @Override
 373  
                                 public void onRequestFail(Throwable cause) {
 374  0
                                         GWT.log("Failed to get modeld for proposal controller init");
 375  0
                                         onReadyCallback.exec(false);
 376  0
                                 }
 377  
                         });
 378  
                                 
 379  
             }
 380  0
     }
 381  
 
 382  
     @Override
 383  
     public void getMetadataForFinalState(final KSAsyncCallback<Metadata> callback){
 384  
                 //Setup View Context
 385  0
                 String idType = null;
 386  0
                 String viewContextId = "";
 387  0
                 if(getViewContext().getIdType() != null){
 388  0
             idType = getViewContext().getIdType().toString();
 389  0
             viewContextId = getViewContext().getId();
 390  0
             if(getViewContext().getIdType()==IdAttributes.IdType.COPY_OF_OBJECT_ID){
 391  0
                     viewContextId = null;
 392  
             }
 393  
                 }
 394  0
                 HashMap<String, String> idAttributes = new HashMap<String, String>();
 395  0
                 if(idType != null){
 396  0
                         idAttributes.put(IdAttributes.ID_TYPE, idType);
 397  
                 }
 398  
 
 399  0
                 idAttributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, currentDocType);
 400  0
                 idAttributes.put(DtoConstants.DTO_STATE, cfg.getState());                                    
 401  0
                 idAttributes.put(DtoConstants.DTO_NEXT_STATE, cfg.getNextState());
 402  0
                 idAttributes.put(DtoConstants.DTO_WORKFLOW_NODE, "Publication Review");
 403  
                 
 404  
                 //Get metadata and complete initializing the screen
 405  0
                 getCourseProposalRpcService().getMetadata(viewContextId, idAttributes, new KSAsyncCallback<Metadata>(){
 406  
                         @Override
 407  
                         public void onSuccess(Metadata result) {
 408  0
                                 callback.onSuccess(result);
 409  0
                         }
 410  
                 });
 411  0
     }
 412  
     
 413  
     protected void configureScreens(final DataModelDefinition modelDefinition, final Callback<Boolean> onReadyCallback){
 414  0
             if (workflowUtil != null){
 415  0
                     workflowUtil.requestAndSetupModel(NO_OP_CALLBACK);        
 416  
             }
 417  
 
 418  0
         CourseRequirementsDataModel.getStatementTypes(new Callback<List<StatementTypeInfo>>() {
 419  
 
 420  
             @Override
 421  
             public void exec(List<StatementTypeInfo> stmtTypes) {
 422  0
                 List<StatementTypeInfo> stmtTypesOut = new ArrayList<StatementTypeInfo>();
 423  0
                 if (stmtTypes != null) {
 424  0
                     for (StatementTypeInfo stmtType : stmtTypes) {
 425  0
                         if (stmtType.getId().contains("kuali.statement.type.course.enrollmentEligibility") ||
 426  
                             stmtType.getId().contains("kuali.statement.type.course.creditConstraints")) {
 427  0
                             continue;
 428  
                         }
 429  0
                         stmtTypesOut.add(stmtType);
 430  
                     }
 431  
                 }
 432  
 
 433  0
                 cfg.setStatementTypes(stmtTypesOut);
 434  0
                 cfg.setModelDefinition(modelDefinition);
 435  0
                 cfg.configure(CourseProposalController.this);
 436  
                 
 437  
                 // Add fields to workflow utils screens (such as blanket approve popup)
 438  
                 // For e.g. the approval popup is different for modifications than other proposals
 439  0
                 if(workflowUtil!=null){
 440  0
                         requestModel(new ModelRequestCallback<DataModel>(){
 441  
                                                 public void onModelReady(DataModel model) {
 442  
                                                         //Only display if this is a modification
 443  0
                                                         String proposalType = model.get("proposal/type");
 444  0
                                                         if ((proposalType!=null) && (proposalType.equals(LUConstants.PROPOSAL_TYPE_COURSE_MODIFY))){        
 445  0
                                                             KSLabel descLabel = new KSLabel();
 446  0
                                                             descLabel.setText(Application.getApplicationContext().getUILabel("course", LUUIConstants.FINAL_APPROVAL_DIALOG));
 447  0
                                                             if (workflowUtil.getApproveDialogue() != null) {
 448  0
                                                                 workflowUtil.getApproveDialogue().addWidget(descLabel);
 449  
                                                             }
 450  0
                                                             workflowUtil.addApproveDialogField("", "startTerm", cfg.generateMessageInfo(LUUIConstants.PROPOSAL_START_TERM), modelDefinition, true, true);
 451  0
                                                             workflowUtil.addApproveDialogField("proposal", "prevEndTerm", cfg.generateMessageInfo(LUUIConstants.PROPOSAL_PREV_END_TERM), modelDefinition, false);
 452  
                                 
 453  0
                                                             workflowUtil.updateApproveFields();                                                            
 454  0
                                                             workflowUtil.progressiveEnableFields();                                                            
 455  0
                                                         }else{
 456  
                                                              // All other types of proposals need to go here
 457  
                                                                 // Ignore this field (so blanket approve works if this is a new course proposal 
 458  
                                                                 // and not a modification)
 459  0
                                                                 workflowUtil.addIgnoreDialogField("proposal/prevEndTerm");
 460  
                                                         }
 461  0
                                                 }  
 462  
                                                 public void onRequestFail(Throwable cause) {
 463  0
                                                 }
 464  
                         });
 465  
                 }
 466  
 
 467  0
                 progressiveEnableFields();
 468  
                 
 469  0
                 onReadyCallback.exec(true);
 470  0
                 KSBlockingProgressIndicator.removeTask(initializingTask);
 471  0
             }
 472  
         });
 473  0
     }
 474  
     
 475  
     /**
 476  
      * This progressively enables/disables screen fields based on other fields present in the screens.
 477  
      *  
 478  
      * NOTE: This metod must be caled after cfg.configure() is called, otherwise path to field mappings won't exist in ApplicationContext
 479  
      */
 480  
     protected void progressiveEnableFields(){
 481  0
                 final FieldDescriptor endTerm = Application.getApplicationContext().getPathToFieldMapping(null,CreditCourseConstants.END_TERM);
 482  0
                 final FieldDescriptor pilotCourse = Application.getApplicationContext().getPathToFieldMapping(null,CreditCourseConstants.PILOT_COURSE);
 483  
                 
 484  0
                 if (pilotCourse != null && endTerm != null){
 485  
                     //Enable and require end term field based on pilot course value in model loaded                
 486  0
                 Boolean enableEndTerm = Boolean.TRUE.equals(cluProposalModel.get(CreditCourseConstants.PILOT_COURSE)) 
 487  
                         || DtoConstants.STATE_RETIRED.equalsIgnoreCase((String)cluProposalModel.get(CreditCourseConstants.STATE));
 488  
                         
 489  0
             BaseSection.progressiveEnableAndRequireFields(enableEndTerm, endTerm);
 490  
 
 491  
                 //Add a click handler to pilot checkbox to toggle enabling and requiredness of end term field
 492  0
                         KSCheckBox pilotCheckbox = ((KSCheckBox)pilotCourse.getFieldWidget());
 493  0
                 pilotCheckbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
 494  
                                 @Override
 495  
                                 public void onValueChange(ValueChangeEvent<Boolean> event) {
 496  
                                         //Disable/enable end term field based on new value of pilot checkbox
 497  0
                     BaseSection.progressiveEnableAndRequireFields(event.getValue(), endTerm);
 498  
                     
 499  
                                 //Clear out endTerm value if pilot course unchecked (as this field is not required when not pilot course)
 500  0
                                 if (!event.getValue()){
 501  0
                                                 ((KSDropDown)((KSPicker)endTerm.getFieldWidget()).getInputWidget()).clear();                                
 502  
                                         }                                                
 503  0
                                 }
 504  
                         });
 505  
                 }
 506  0
     }
 507  
 
 508  
     @Override
 509  
     @SuppressWarnings("unchecked")
 510  
     public void requestModel(Class modelType, final ModelRequestCallback callback) {
 511  0
         if(modelType == ReferenceModel.class){
 512  0
                 if (cluProposalModel != null){
 513  0
                         ReferenceModel ref = new ReferenceModel();
 514  
 
 515  0
                         if(cluProposalModel.get(cfg.getProposalPath()) != null){
 516  0
                             ref.setReferenceId((String)cluProposalModel.get(cfg.getProposalPath()+"/id"));
 517  
                         } else {
 518  0
                                 ref.setReferenceId(null);
 519  
                         }
 520  
                         
 521  
                         //Use the referenceAttribute to store misc data from the parent model like reference name, etc
 522  0
                         if(cluProposalModel.get(cfg.getProposalPath()) != null){
 523  0
                                 Map<String, String> attributes = new HashMap<String, String>();
 524  0
                                 attributes.put("name", (String)cluProposalModel.get(cfg.getProposalPath()+"/name"));
 525  0
                                 ref.setReferenceAttributes(attributes);
 526  0
                         } else {
 527  0
                                 ref.setReferenceAttributes(null);
 528  
                         }
 529  
 
 530  0
                         ref.setReferenceTypeKey(cfg.getProposalReferenceTypeKey());
 531  0
                         ref.setReferenceType(cfg.getProposalReferenceObjectType());
 532  0
                         ref.setReferenceState(getViewContext().getState());
 533  
 
 534  0
                         callback.onModelReady(ref);
 535  0
                 }
 536  0
         } else if (modelType == Data.class){
 537  0
                 requestModel(cfg.getModelId(), callback);
 538  
         } else {
 539  0
             super.requestModel(modelType, callback);
 540  
         }
 541  
 
 542  0
     }
 543  
 
 544  
     protected void getCluProposalFromWorkflowId(@SuppressWarnings("rawtypes") final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 545  0
         KSBlockingProgressIndicator.addTask(loadDataTask);
 546  0
         workflowUtil.getDataIdFromWorkflowId(getViewContext().getId(), new KSAsyncCallback<String>(){
 547  
                         @Override
 548  
                         public void handleFailure(Throwable caught) {
 549  0
                 Window.alert("Error loading Proposal from Workflow Document: "+caught.getMessage());
 550  0
                 createNewCluProposalModel(callback, workCompleteCallback);
 551  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 552  0
                         }
 553  
 
 554  
                         @Override
 555  
                         public void onSuccess(String proposalId) {
 556  0
                                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 557  0
                                 getCluProposalFromProposalId(proposalId, callback, workCompleteCallback);
 558  0
                         }
 559  
         });
 560  0
     }
 561  
 
 562  
     protected void getCluProposalFromProposalId(String id, @SuppressWarnings("rawtypes") final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 563  0
             KSBlockingProgressIndicator.addTask(loadDataTask);
 564  0
             getCourseProposalRpcService().getData(id, new KSAsyncCallback<Data>(){
 565  
 
 566  
                         @Override
 567  
                         public void handleFailure(Throwable caught) {
 568  0
                 Window.alert("Error loading Proposal: "+caught.getMessage());
 569  0
                 createNewCluProposalModel(callback, workCompleteCallback);
 570  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 571  0
                         }
 572  
 
 573  
                         @Override
 574  
                         public void onSuccess(Data result) {
 575  0
                                 cluProposalModel.setRoot(result);
 576  0
                         setHeaderTitle();
 577  0
                         setLastUpdated();
 578  0
                 reqDataModel.retrieveStatementTypes(cluProposalModel.<String>get("id"), new Callback<Boolean>() {
 579  
                     @Override
 580  
                     public void exec(Boolean result) {
 581  0
                        if(result){
 582  0
                           getCourseComparisonModelAndReqs(callback, workCompleteCallback);
 583  
                        }
 584  0
                     }
 585  
                 });
 586  0
                         }
 587  
 
 588  
             });
 589  0
     }
 590  
 
 591  
     @SuppressWarnings("unchecked")
 592  
         protected void getCourseComparisonModelAndReqs(final ModelRequestCallback proposalModelRequestCallback, final Callback<Boolean> workCompleteCallback){
 593  0
                 if(cluProposalModel.get(VERSION_KEY) != null && !((String)cluProposalModel.get(VERSION_KEY)).equals("")){
 594  0
                         courseServiceAsync.getData((String)cluProposalModel.get(VERSION_KEY), new KSAsyncCallback<Data>(){
 595  
         
 596  
                             @Override
 597  
                     public void handleFailure(Throwable caught) {
 598  0
                         Window.alert("Error loading Proposal: "+caught.getMessage());
 599  0
                         createNewCluProposalModel(proposalModelRequestCallback, workCompleteCallback);
 600  0
                         KSBlockingProgressIndicator.removeTask(loadDataTask);
 601  0
                     }
 602  
 
 603  
                 @Override
 604  
                 public void onSuccess(Data result) {
 605  
                         // ??? why result would be null ever?
 606  0
                     if (result != null) 
 607  0
                         comparisonModel.setRoot(result);
 608  
 
 609  0
                     reqDataModel.retrieveStatementTypes(cluProposalModel.<String>get("id"), new Callback<Boolean>() {
 610  
                                    @Override
 611  
                                    public void exec(Boolean result) {
 612  0
                                            if (result) {
 613  0
                                                    KSBlockingProgressIndicator.removeTask(loadDataTask);
 614  0
                                 reqDataModelComp.retrieveStatementTypes(comparisonModel.<String>get("id"), new Callback<Boolean>() {
 615  
                                     @Override
 616  
                                     public void exec(Boolean result) {
 617  0
                                         if (result) {
 618  0
                                             KSBlockingProgressIndicator.removeTask(loadDataTask);
 619  
                                          }
 620  0
                                     }
 621  
                                 });
 622  0
                                 proposalModelRequestCallback.onModelReady(cluProposalModel);
 623  0
                                 workCompleteCallback.exec(true);
 624  
                                           }
 625  0
                                    }
 626  
                            });
 627  0
                }
 628  
             });
 629  
         } else {
 630  0
             proposalModelRequestCallback.onModelReady(cluProposalModel);
 631  0
             workCompleteCallback.exec(true);
 632  0
             KSBlockingProgressIndicator.removeTask(loadDataTask);
 633  
         }
 634  0
     }
 635  
 
 636  
     @SuppressWarnings("unchecked")
 637  
     protected void createNewCluProposalModel(final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 638  0
         Data data = new Data();
 639  0
             cluProposalModel.setRoot(data);
 640  
         
 641  0
         Data proposalData = new Data();
 642  0
         proposalData.set(new Data.StringKey("type"), currentDocType);
 643  0
         data.set(new Data.StringKey("proposal"), proposalData);                
 644  0
         if (cfg.getNextState() == null || cfg.getNextState().isEmpty()){
 645  0
                 proposalData.set(new Data.StringKey("workflowNode"), "PreRoute");
 646  
         }
 647  
         
 648  0
         isNew = true;
 649  0
         setHeaderTitle();
 650  0
         setLastUpdated();
 651  0
         callback.onModelReady(cluProposalModel);
 652  0
         workCompleteCallback.exec(true);
 653  0
     }
 654  
     
 655  
     protected void createModifyCluProposalModel(String versionComment, final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 656  0
         Data data = new Data();
 657  0
         cluProposalModel.setRoot(data);        
 658  
         
 659  0
         this.currentDocType = getViewContext().getAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME);
 660  0
         Data proposalData = new Data();
 661  0
         proposalData.set(new Data.StringKey("type"), currentDocType);
 662  0
         data.set(new Data.StringKey("proposal"), proposalData);
 663  0
         if (cfg.getNextState() == null && cfg.getNextState().isEmpty()){
 664  0
                 proposalData.set(new Data.StringKey("workflowNode"), "PreRoute");
 665  
         }
 666  
                 
 667  0
         Data versionData = new Data();
 668  0
         versionData.set(new Data.StringKey("versionIndId"), getViewContext().getId());
 669  0
         versionData.set(new Data.StringKey("versionComment"), versionComment);
 670  0
         data.set(new Data.StringKey("versionInfo"), versionData);
 671  
         
 672  0
         cluProposalRpcServiceAsync.saveData(cluProposalModel.getRoot(), new AsyncCallback<DataSaveResult>() {
 673  
                         public void onSuccess(DataSaveResult result) {
 674  0
                                 cluProposalModel.setRoot(result.getValue());
 675  0
                                 setHeaderTitle();
 676  0
                         setLastUpdated();
 677  
                         //add to recently viewed now that we know the id of proposal
 678  0
                         ViewContext docContext = new ViewContext();
 679  0
                         docContext.setId((String) cluProposalModel.get(cfg.getProposalPath()+"/id"));
 680  0
                         docContext.setIdType(IdType.KS_KEW_OBJECT_ID);
 681  
                         //RecentlyViewedHelper.addDocument(getProposalTitle(), 
 682  
                         //        HistoryManager.appendContext(AppLocations.Locations.COURSE_PROPOSAL.getLocation(), docContext)
 683  
                         //                + "/SUMMARY");
 684  0
                         getCourseComparisonModelAndReqs(callback, workCompleteCallback);
 685  
                         
 686  
                         // We need to update the current view context so that if the user clicks the back button it doesn't 
 687  
                         // create a duplicate course proposal. 
 688  0
                         getViewContext().setIdType(docContext.getIdType());
 689  0
                         getViewContext().setId(docContext.getId());
 690  
                         
 691  0
                         }
 692  
                         
 693  
                         public void onFailure(Throwable caught) {
 694  0
                 Window.alert("Error loading Proposal: "+caught.getMessage());
 695  0
                 createNewCluProposalModel(callback, workCompleteCallback);
 696  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 697  0
                         }
 698  
                 });
 699  0
     }
 700  
 
 701  
     @SuppressWarnings("unchecked")
 702  
         protected void createCopyCourseModel(String originalCluId, final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 703  
 
 704  0
             cluProposalRpcServiceAsync.createCopyCourse(originalCluId, new AsyncCallback<DataSaveResult>() {
 705  
                         public void onSuccess(DataSaveResult result) {
 706  0
                                 cluProposalModel.setRoot(result.getValue());
 707  
                                 
 708  
                                 //Add in a blank proposal placeholder
 709  0
                         Data proposalData = new Data();
 710  0
                         cluProposalModel.getRoot().set(new Data.StringKey("proposal"), proposalData);
 711  0
                         if (cfg.getNextState() == null || cfg.getNextState().isEmpty()){
 712  0
                             proposalData.set(new Data.StringKey("workflowNode"), "PreRoute");
 713  
                         }
 714  
                         
 715  0
                         isNew = true;
 716  0
                                 setHeaderTitle();
 717  0
                         setLastUpdated();
 718  
 
 719  0
                         callback.onModelReady(cluProposalModel);
 720  0
                         workCompleteCallback.exec(true);
 721  0
                         }
 722  
                         
 723  
                         public void onFailure(Throwable caught) {
 724  0
                 Window.alert("Error loading Proposal: "+caught.getMessage());
 725  0
                 createNewCluProposalModel(callback, workCompleteCallback);
 726  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 727  0
                         }
 728  
                 });
 729  0
     }
 730  
     
 731  
     @SuppressWarnings("unchecked")
 732  
         protected void createCopyCourseProposalModel(String originalProposalId, final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 733  
 
 734  0
             cluProposalRpcServiceAsync.createCopyCourseProposal(originalProposalId, new AsyncCallback<DataSaveResult>() {
 735  
                         public void onSuccess(DataSaveResult result) {
 736  0
                                 cluProposalModel.setRoot(result.getValue());
 737  0
                         setHeaderTitle();
 738  0
                         setLastUpdated();
 739  
                         //add to recently viewed now that we know the id of proposal
 740  0
                         ViewContext docContext = new ViewContext();
 741  0
                         docContext.setId((String) cluProposalModel.get(cfg.getProposalPath()+"/id"));
 742  0
                         docContext.setIdType(IdType.KS_KEW_OBJECT_ID);
 743  0
                         RecentlyViewedHelper.addDocument(getProposalTitle(), 
 744  
                                         HistoryManager.appendContext(AppLocations.Locations.COURSE_PROPOSAL.getLocation(), docContext)
 745  
                                         + "/COURSE_INFO");
 746  
                         
 747  
                         // We need to update the current view context so that if the user clicks the back button it doesn't 
 748  
                         // create a duplicate course proposal. 
 749  0
                         getViewContext().setIdType(docContext.getIdType());
 750  0
                         getViewContext().setId(docContext.getId());
 751  
                         
 752  0
                         callback.onModelReady(cluProposalModel);
 753  0
                         workCompleteCallback.exec(true);
 754  0
                         }
 755  
                         
 756  
                         public void onFailure(Throwable caught) {
 757  0
                 Window.alert("Error loading Proposal: "+caught.getMessage());
 758  0
                 createNewCluProposalModel(callback, workCompleteCallback);
 759  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 760  0
                         }
 761  
                 });
 762  0
     }
 763  
     
 764  
     public void doSaveAction(final SaveActionEvent saveActionEvent){
 765  0
         requestModel(new ModelRequestCallback<DataModel>() {
 766  
             @Override
 767  
             public void onModelReady(DataModel model) {
 768  0
                 CourseProposalController.this.updateModelFromCurrentView();
 769  
 
 770  0
                 if (isStartViewShowing()){
 771  
                         //This call required so fields in start section, which also appear in
 772  
                         //other sections don't get overridden from updateModel call above.
 773  0
                         getStartPopupView().updateModel();
 774  
                 }
 775  
 
 776  0
                     model.validate(new Callback<List<ValidationResultInfo>>() {
 777  
                     @Override
 778  
                     public void exec(List<ValidationResultInfo> result) {
 779  
 
 780  0
                             boolean isSectionValid = isValid(result, true);
 781  
 
 782  0
                             if(isSectionValid){
 783  0
                             if (startSectionRequired()){
 784  0
                                 showStartPopup(NO_OP_CALLBACK);
 785  0
                                 saveActionEvent.doActionComplete();
 786  
                             }
 787  
                             else{
 788  0
                                     saveProposalClu(saveActionEvent);
 789  
                             }
 790  
                             }
 791  
                             else{
 792  
                                     //saveActionEvent.doActionComplete();
 793  0
                                     KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 794  
                             }
 795  
 
 796  0
                     }
 797  
                 });
 798  0
             }
 799  
 
 800  
             @Override
 801  
             public void onRequestFail(Throwable cause) {
 802  0
                     saveActionEvent.doActionComplete();
 803  0
                 GWT.log("Unable to retrieve model for validation and save", cause);
 804  0
             }
 805  
 
 806  
         });
 807  
 
 808  0
     }
 809  
 
 810  
     public boolean startSectionRequired(){
 811  0
         String proposalId = cluProposalModel.get(cfg.getProposalPath()+"/id");
 812  
         
 813  
         //Defaulting the proposalTitle to courseTitle, this way course data gets set and assembler doesn't
 814  
         //complain. This may not be the correct approach.
 815  0
         String proposalTitle = cluProposalModel.get(cfg.getProposalTitlePath());
 816  0
         String courseTitle = cluProposalModel.get(cfg.getCourseTitlePath());
 817  0
         if (proposalTitle == null || proposalTitle.isEmpty()){
 818  0
             cluProposalModel.set(QueryPath.parse(cfg.getProposalTitlePath()), courseTitle);
 819  
         }
 820  
         
 821  0
             return proposalId==null && !CourseProposalController.this.isStartViewShowing() && !hasTitles(proposalTitle, courseTitle);
 822  
     }
 823  
 
 824  
     private boolean hasTitles(String proposalTitle, String courseTitle){
 825  0
             return (proposalTitle != null && !proposalTitle.isEmpty()) && (courseTitle != null && !courseTitle.isEmpty());
 826  
     }
 827  
     
 828  
     public void saveProposalClu(final SaveActionEvent saveActionEvent){
 829  0
             KSBlockingProgressIndicator.addTask(saving);
 830  0
         getCourseProposalRpcService().saveData(cluProposalModel.getRoot(), new KSAsyncCallback<DataSaveResult>(){
 831  
 
 832  
             @Override
 833  
             public void handleFailure(Throwable caught) {
 834  0
                 GWT.log("Save Failed.", caught);
 835  0
                 KSBlockingProgressIndicator.removeTask(saving);
 836  0
                 KSNotifier.add(new KSNotification("Save Failed on server. Please try again.", false, true, 5000));
 837  0
             }
 838  
                 
 839  
             @Override
 840  
             public void handleVersionMismatch(Throwable caught) {
 841  0
                 super.handleVersionMismatch(caught);
 842  0
                 KSBlockingProgressIndicator.removeTask(saving);
 843  0
             }
 844  
 
 845  
             public void onSuccess(DataSaveResult result) {
 846  0
                 KSBlockingProgressIndicator.removeTask(saving);
 847  
 
 848  0
                                 Application.getApplicationContext().clearValidationWarnings();
 849  0
                                 Application.getApplicationContext().addValidationWarnings(result.getValidationResults());
 850  
                         
 851  0
                                 if(ValidatorClientUtils.hasErrors(result.getValidationResults())){
 852  0
                         isValid(result.getValidationResults(), false, true);
 853  0
                     saveActionEvent.setGotoNextView(false);
 854  0
                     saveActionEvent.doActionComplete();
 855  0
                     KSNotifier.add(new KSNotification("Save Failed. There were validation errors.", false, true, 5000));
 856  
                 }else{
 857  
                                 
 858  0
                         saveActionEvent.setSaveSuccessful(true);
 859  0
                         cluProposalModel.setRoot(result.getValue());
 860  0
                         String title = getProposalTitle();
 861  0
                         View currentView = getCurrentView();
 862  0
                                      if (currentView instanceof SectionView){
 863  0
                                             ((SectionView)currentView).updateView(cluProposalModel);
 864  0
                                             ((SectionView) currentView).resetDirtyFlags();
 865  
                         }
 866  0
                     saveActionEvent.doActionComplete();
 867  
                             
 868  0
                                     ViewContext context = CourseProposalController.this.getViewContext();
 869  0
                                     context.setId((String)cluProposalModel.get(proposalPath+"/id"));
 870  0
                                     context.setIdType(IdType.KS_KEW_OBJECT_ID);
 871  
                                     
 872  
                                     //Always update the status after a save.
 873  0
                                     if(workflowUtil != null){
 874  0
                                             workflowUtil.refresh();
 875  
                                     }
 876  
                                             
 877  0
                                     setHeaderTitle();
 878  0
                                     setLastUpdated();
 879  0
                                     HistoryManager.logHistoryChange();
 880  0
                                if(isNew){
 881  0
                                        RecentlyViewedHelper.addDocument(getProposalTitle(), 
 882  
                                         HistoryManager.appendContext(AppLocations.Locations.COURSE_PROPOSAL.getLocation(), context)
 883  
                                                 + "/SUMMARY");
 884  
                                }
 885  0
                                else if(!currentTitle.equals(title)){
 886  0
                                        RecentlyViewedHelper.updateTitle(currentTitle, title, (String)cluProposalModel.get(proposalPath+"/id"));
 887  
                                }
 888  0
                                isNew = false;
 889  
                                             
 890  0
                                     if(saveActionEvent.gotoNextView()){
 891  0
                                             CourseProposalController.this.showNextViewOnMenu();
 892  
                                     }
 893  
                                             
 894  0
                                     if (ValidatorClientUtils.hasWarnings(result.getValidationResults())){
 895  0
                                             if (!saveActionEvent.gotoNextView()){
 896  
                                                     //Need to display warnings when view has not changed.
 897  0
                                                     isValid(result.getValidationResults(), false, true);
 898  
                                             }
 899  0
                                             KSNotifier.show("Saved with Warnings");
 900  
                                     } else {
 901  0
                                             KSNotifier.show("Save Successful");
 902  
                                     }                                  
 903  
                        }
 904  0
             }
 905  
         });
 906  
 
 907  0
     }
 908  
 
 909  
     public void setLastUpdated(){
 910  0
             Date lastUpdated = (Date)cluProposalModel.get(UPDATED_KEY);
 911  0
             if(lastUpdated != null){
 912  0
                     setContentInfo("Last Updated: " + df.format(lastUpdated));
 913  
             }
 914  
             else{
 915  0
                     setContentInfo("");
 916  
             }
 917  0
     }
 918  
 
 919  
     @Override
 920  
         public void beforeShow(final Callback<Boolean> onReadyCallback){
 921  0
             Application.getApplicationContext().clearCrossConstraintMap(null);
 922  0
             Application.getApplicationContext().clearPathToFieldMapping(null);
 923  0
             Application.getApplicationContext().clearValidationWarnings();
 924  0
             Application.getApplicationContext().setParentPath("");
 925  
                        
 926  0
             intializeView(onReadyCallback);
 927  0
         }
 928  
 
 929  
     //Before show is called before the model is bound to the widgets. We need to update cross constraints and re-display 
 930  
     // validation warnings after widget binding
 931  
     //This gets called twice which is not optimal
 932  
         @Override
 933  
         public <V extends Enum<?>> void showView(final V viewType, final Callback<Boolean> onReadyCallback) {
 934  0
                 Callback<Boolean> finalizeView = new Callback<Boolean>(){
 935  
                     
 936  
                         public void exec(Boolean result) {   // Called from at least CourseSumamryConfigurer.generateProposalSummarySection.verticalSection.beforeShow.exec [KSCM-250]
 937  
                                 
 938  
                             //Update cross constraints
 939  0
                                 for(HasCrossConstraints crossConstraint:Application.getApplicationContext().getCrossConstraints(null)){
 940  0
                                 crossConstraint.reprocessWithUpdatedConstraints();
 941  
                         }                                
 942  
                                 
 943  
                                 //When showing summary section make sure data gets validated in case there are warnings.
 944  
                                 //TODO: Is it possible to cut down on this validation so it doesn't have to validate every time.
 945  0
                                 if (viewType == CourseSections.SUMMARY){
 946  
                                     
 947  0
                                         KSBlockingProgressIndicator.addTask(initializingTask);
 948  
                                         
 949  0
                                         courseServiceAsync.validate(cluProposalModel.getRoot(), new KSAsyncCallback<List<ValidationResultInfo>>(){ // server-side call
 950  
                                             
 951  
                                                 @Override
 952  
                                                 public void onSuccess(List<ValidationResultInfo> result) {
 953  
                                                     
 954  0
                                                         Application.getApplicationContext().clearValidationWarnings();
 955  0
                                                         Application.getApplicationContext().addValidationWarnings(result);
 956  
                                                         
 957  0
                                                         showWarnings();
 958  
                                                         
 959  0
                                                         KSBlockingProgressIndicator.removeTask(initializingTask);
 960  0
                                                 }                                                
 961  
                                         });                                        
 962  
                                 } else {
 963  
                                     
 964  0
                                         showWarnings();                                        
 965  
                                 }
 966  
                                 
 967  0
                                 onReadyCallback.exec(result);
 968  0
                         }
 969  
         };
 970  
         
 971  0
                 super.showView(viewType, finalizeView);
 972  0
         }
 973  
         
 974  
 
 975  
    @Override
 976  
    public void showDefaultView(Callback<Boolean> onReadyCallback) {
 977  0
            if(isNew){
 978  0
                    super.showFirstView(onReadyCallback);
 979  
            }
 980  
            else{
 981  0
                    super.showDefaultView(onReadyCallback);
 982  
            }
 983  0
    }
 984  
 
 985  
         @Override
 986  
     public void setParentController(Controller controller) {
 987  0
         super.setParentController(controller);
 988  0
     }
 989  
 
 990  
         @Override
 991  
         /**
 992  
          * Override method to determine if user has access to screen and if they have permission to open or initiate the proposal.
 993  
          * 
 994  
          *  FIXME: This method should not require a permissionType as a parameter
 995  
          */
 996  
         public void checkAuthorization(final AuthorizationCallback authCallback) {
 997  0
                 GWT.log("Attempting Auth Check.", null);
 998  
         
 999  
                 //Get attributes required for permission check
 1000  0
                 Map<String,String> attributes = new HashMap<String,String>();
 1001  0
                 addPermissionAttributes(attributes);
 1002  
 
 1003  
                 //Note: Additional attributes required for permission check (eg. permission details and role qualifiers) will
 1004  
                 //be determined server side in the AbstractDataService.isAuthorized method. All that is required here is
 1005  
                 //id of the proposal object)
 1006  0
                 cluProposalRpcServiceAsync.isAuthorized(getViewContext().getPermissionType(), attributes, new KSAsyncCallback<Boolean>(){
 1007  
 
 1008  
                         @Override
 1009  
                         public void handleFailure(Throwable caught) {
 1010  0
                                 authCallback.isNotAuthorized("Error checking authorization.");
 1011  0
                                 GWT.log("Error checking proposal authorization.", caught);
 1012  0
                 Window.alert("Error Checking Proposal Authorization: "+caught.getMessage());
 1013  0
                         }
 1014  
 
 1015  
                         @Override
 1016  
                         public void onSuccess(Boolean result) {
 1017  0
                                 GWT.log("Succeeded checking auth for permission type '" + getViewContext().getPermissionType().toString() + "' with result: " + result, null);
 1018  0
                                 if (Boolean.TRUE.equals(result)) {
 1019  0
                                         authCallback.isAuthorized();
 1020  
                                 }
 1021  
                                 else {
 1022  0
                                         authCallback.isNotAuthorized("User is not authorized: " + getViewContext().getPermissionType().toString());
 1023  
                                 }
 1024  0
                         }
 1025  
             });
 1026  0
         }
 1027  
 
 1028  
     @Override
 1029  
     public void setViewContext(ViewContext viewContext) {
 1030  
         //Determine the permission type being checked
 1031  
         
 1032  
 //        viewContext.setPermissionType(PermissionType.MY_PERM);
 1033  
         
 1034  
         
 1035  
         
 1036  0
         if (viewContext.getId() != null && !viewContext.getId().isEmpty()) {
 1037  0
             if (viewContext.getIdType() != IdType.COPY_OF_OBJECT_ID
 1038  
                     && viewContext.getIdType() != IdType.COPY_OF_KS_KEW_OBJECT_ID) {
 1039  
                 //Id provided, and not a copy id, so opening an existing proposal
 1040  0
                 viewContext.setPermissionType(PermissionType.OPEN);
 1041  
             } else {
 1042  
                 //Copy id provided, so creating a proposal for modification
 1043  0
                 viewContext.setPermissionType(PermissionType.INITIATE);
 1044  
             }
 1045  
         } else {
 1046  
             //No id in view context, so creating new empty proposal
 1047  0
             viewContext.setPermissionType(PermissionType.INITIATE);
 1048  
         }
 1049  
         
 1050  0
         context = viewContext;
 1051  0
     }
 1052  
 
 1053  
         /**
 1054  
          * This method adds any permission attributes required for checking permissions
 1055  
          */
 1056  
         public void addPermissionAttributes(Map<String, String> attributes){
 1057  0
                 ViewContext viewContext = getViewContext();
 1058  
 
 1059  
                 //Get the id to use to check permissions, this could either be the proposal id or the workflow document id,
 1060  
                 //will pass the id & id type as attributes to permission service.
 1061  0
                 if ( (viewContext.getId() != null) && (!"".equals(viewContext.getId())) ) {
 1062  0
                         attributes.put(viewContext.getIdType().toString(), viewContext.getId());
 1063  
                 }
 1064  
                 
 1065  
                 //Determine the permission type being checked
 1066  0
             if(viewContext.getId() != null && !viewContext.getId().isEmpty()){
 1067  0
                     if(viewContext.getIdType() != IdType.COPY_OF_OBJECT_ID && viewContext.getIdType() != IdType.COPY_OF_KS_KEW_OBJECT_ID){
 1068  
                             //Id provided, and not a copy id, so opening an existing proposal
 1069  0
                             attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_CREATE);
 1070  
                     } 
 1071  
                         //Copy id provided, so creating a proposal for modification or retire                    
 1072  0
                     else if (currentDocType.equals(LUConstants.PROPOSAL_TYPE_COURSE_MODIFY)){                            
 1073  0
                                   attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_MODIFY);
 1074  
                                } 
 1075  0
                                else if (currentDocType.equals(LUConstants.PROPOSAL_TYPE_COURSE_RETIRE)){
 1076  0
                                 attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_RETIRE);
 1077  
                            } 
 1078  
                          else{
 1079  
                               //No id in view context, so creating new empty proposal
 1080  0
                                  attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_CREATE);                    
 1081  
                          }
 1082  
             }
 1083  0
         }
 1084  
         
 1085  
         @Override
 1086  
         public boolean isAuthorizationRequired() {
 1087  0
                 return true;
 1088  
         }
 1089  
 
 1090  
         @Override
 1091  
         public void setAuthorizationRequired(boolean required) {
 1092  0
                 throw new UnsupportedOperationException();
 1093  
         }
 1094  
 
 1095  
     protected void setHeaderTitle(){
 1096  
             String title;
 1097  0
             if (cluProposalModel.get(cfg.getProposalTitlePath()) != null){
 1098  0
                     title = getProposalTitle();
 1099  
             }
 1100  
             else{
 1101  0
                     title = "New Course (Proposal)";
 1102  
             }
 1103  0
             this.setContentTitle(title);
 1104  0
             this.setName(title);
 1105  0
             WindowTitleUtils.setContextTitle(title);
 1106  0
                 currentTitle = title;
 1107  0
     }
 1108  
 
 1109  
         @Override
 1110  
         public WorkflowUtilities getWfUtilities() {
 1111  0
                 return workflowUtil;
 1112  
         }
 1113  
 
 1114  
         @Override
 1115  
         public void beforeViewChange(final Enum<?> viewChangingTo, final Callback<Boolean> okToChange) {
 1116  
                 //Make sure the course information data is bound before viewing any other sections for cross field constraints
 1117  0
                 final Callback<Boolean> reallyOkToChange = new Callback<Boolean>(){
 1118  
                         @Override
 1119  
                         public void exec(Boolean result) {
 1120  0
                                 if(result){
 1121  0
                                         if(CourseSections.GOVERNANCE.equals(viewChangingTo)){
 1122  0
                                                 getView(CourseSections.COURSE_INFO, new Callback<View>(){
 1123  
                                                         @Override
 1124  
                                                         public void exec(final View view) {
 1125  0
                                                                 if(view!=null && view instanceof SectionView){
 1126  0
                                                                         requestModel(new ModelRequestCallback<DataModel>(){
 1127  
                                                                                 public void onModelReady(DataModel model) {
 1128  0
                                                                                         ((SectionView)view).updateWidgetData(model);
 1129  0
                                                                                         okToChange.exec(true);
 1130  0
                                                                                 }
 1131  
                                                                                 public void onRequestFail(Throwable cause) {
 1132  0
                                                                                         okToChange.exec(false);
 1133  0
                                                                                 }
 1134  
                                                                         });
 1135  
                                                                 }else{
 1136  0
                                                                         okToChange.exec(true);
 1137  
                                                                 }
 1138  0
                                                         }});
 1139  
                                         } else
 1140  0
                                                 okToChange.exec(true);                                        
 1141  
                                 } else         
 1142  0
                                         okToChange.exec(false);
 1143  0
                         }
 1144  
                 };
 1145  
                 
 1146  
                 //We do this check here because theoretically the subcontroller views
 1147  
                 //will display their own messages to the user to give them a reason why the view
 1148  
                 //change has been cancelled, otherwise continue to check for reasons not to change
 1149  
                 //with this controller
 1150  0
                 super.beforeViewChange(viewChangingTo, new Callback<Boolean>(){
 1151  
 
 1152  
                         @Override
 1153  
                         public void exec(Boolean result) {
 1154  0
                                 if(result){
 1155  0
                                         if(getCurrentView() instanceof SectionView && ((SectionView)getCurrentView()).isDirty()){
 1156  0
                                                 ButtonGroup<YesNoCancelEnum> buttonGroup = new YesNoCancelGroup();
 1157  0
                                                 final ButtonMessageDialog<YesNoCancelEnum> dialog = new ButtonMessageDialog<YesNoCancelEnum>("Warning", "You may have unsaved changes.  Save changes?", buttonGroup);
 1158  0
                                                 buttonGroup.addCallback(new Callback<YesNoCancelEnum>(){
 1159  
 
 1160  
                                                         @Override
 1161  
                                                         public void exec(YesNoCancelEnum result) {
 1162  0
                                                                 switch(result){
 1163  
                                                                         case YES:
 1164  0
                                                                                 dialog.hide();
 1165  0
                                                                                 final SaveActionEvent e = new SaveActionEvent();
 1166  0
                                                                                 e.setActionCompleteCallback(new ActionCompleteCallback(){
 1167  
 
 1168  
                                                                                         @Override
 1169  
                                                                                         public void onActionComplete(ActionEvent action) {
 1170  0
                                                                                                 if(e.isSaveSuccessful()){
 1171  0
                                                                                                         reallyOkToChange.exec(true);
 1172  
                                                                                                 }
 1173  
                                                                                                 else{
 1174  0
                                                                                                         reallyOkToChange.exec(false);
 1175  
                                                                                                 }
 1176  0
                                                                                         }
 1177  
                                                                                         
 1178  
                                                                                 });
 1179  0
                                                                                 fireApplicationEvent(e);
 1180  0
                                                                                 break;
 1181  
                                                                         case NO:
 1182  
                                                                                 //Force a model request from server
 1183  0
                                                                                 getCurrentModel(new ModelRequestCallback<DataModel>(){
 1184  
 
 1185  
                                                                                         @Override
 1186  
                                                                                         public void onModelReady(DataModel model) {
 1187  0
                                                                                                 if (getCurrentView()instanceof Section){
 1188  0
                                                                                                     ((Section) getCurrentView()).resetFieldInteractionFlags();
 1189  
                                                                                                 }
 1190  0
                                                                                                 reallyOkToChange.exec(true);
 1191  0
                                                                                                 dialog.hide();
 1192  0
                                                                                         }
 1193  
 
 1194  
                                                                                         @Override
 1195  
                                                                                         public void onRequestFail(Throwable cause) {
 1196  
                                                                                                 //TODO Is this correct... do we want to stop view change if we can't restore the data?  Possibly traps the user
 1197  
                                                                                                 //if we don't it messes up saves, possibly warn the user that it failed and continue?
 1198  0
                                                                                                 reallyOkToChange.exec(false);
 1199  0
                                                                                                 dialog.hide();
 1200  0
                                                                                                 GWT.log("Unable to retrieve model for data restore on view change with no save", cause);
 1201  0
                                                                                         }},
 1202  
                                                                                         NO_OP_CALLBACK);
 1203  
 
 1204  0
                                                                                 break;
 1205  
                                                                         case CANCEL:
 1206  0
                                                                                 reallyOkToChange.exec(false);
 1207  0
                                                                                 dialog.hide();
 1208  
                                                                                 // Because this event fires after the history change event we need to "undo" the history events. 
 1209  0
                                                                                 HistoryManager.logHistoryChange();  
 1210  
                                                                                 break;
 1211  
                                                                 }
 1212  0
                                                         }
 1213  
                                                 });
 1214  0
                                                 dialog.addCloseLinkClickHandler(new ClickHandler() {
 1215  
                             
 1216  
                             @Override
 1217  
                             public void onClick(ClickEvent event) {
 1218  0
                                 okToChange.exec(false);
 1219  0
                                 dialog.hide();
 1220  
                                 // Because this event fires after the history change event we need to "undo" the history events. 
 1221  0
                                 HistoryManager.logHistoryChange();  
 1222  0
                             }
 1223  
                         });
 1224  0
                                                 dialog.show();
 1225  0
                                         }
 1226  
                                         else{
 1227  0
                                                 reallyOkToChange.exec(true);
 1228  
                                         }
 1229  
                                 }
 1230  
                                 else{
 1231  0
                                         reallyOkToChange.exec(false);
 1232  
                                 }
 1233  0
                         }
 1234  
                 });
 1235  0
         }
 1236  
         
 1237  
     public KSButton getSaveButton(){
 1238  0
             if(currentDocType != LUConstants.PROPOSAL_TYPE_COURSE_MODIFY && currentDocType != LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN){
 1239  0
                 return new KSButton("Save and Continue", new ClickHandler(){
 1240  
                             public void onClick(ClickEvent event) {
 1241  0
                                     CourseProposalController.this.fireApplicationEvent(new SaveActionEvent(true));
 1242  0
                             }
 1243  
                         });
 1244  
             }
 1245  
             else{
 1246  0
                     return new KSButton("Save", new ClickHandler(){
 1247  
                 public void onClick(ClickEvent event) {
 1248  0
                     CourseProposalController.this.fireApplicationEvent(new SaveActionEvent(false));
 1249  0
                 }
 1250  
             });
 1251  
             }
 1252  
     }
 1253  
     
 1254  
     public KSButton getCancelButton(final Enum<?> summaryView){
 1255  
             
 1256  0
         return new KSButton("Cancel", ButtonStyle.ANCHOR_LARGE_CENTERED, new ClickHandler(){
 1257  
                     public void onClick(ClickEvent event) {
 1258  0
                             if(!isNew){
 1259  0
                                     CourseProposalController.this.showView(summaryView);
 1260  
                             }
 1261  
                             else{
 1262  0
                                     Application.navigate(AppLocations.Locations.CURRICULUM_MANAGEMENT.getLocation());
 1263  
                             }
 1264  0
                     }
 1265  
                 });
 1266  
 
 1267  
     }
 1268  
         
 1269  
         @Override
 1270  
         public void onHistoryEvent(String historyStack) {
 1271  0
                 super.onHistoryEvent(historyStack);
 1272  
                 //we dont want to add proposals that are brand new before saving, or copy addresses (as they will initiate
 1273  
                 //the modify/copy logic again if called)
 1274  0
                 if(cluProposalModel.get(cfg.getProposalTitlePath()) != null && 
 1275  
                                 this.getViewContext().getIdType() != IdType.COPY_OF_OBJECT_ID){
 1276  0
                         RecentlyViewedHelper.addCurrentDocument(getProposalTitle());
 1277  
                 }
 1278  0
         }
 1279  
         
 1280  
         private String getProposalTitle(){
 1281  0
                 StringBuffer sb = new StringBuffer();
 1282  0
                 sb.append(cluProposalModel.get(cfg.getProposalTitlePath()));
 1283  0
                 sb.append(" (Proposal)");
 1284  0
                 return sb.toString();
 1285  
         }
 1286  
 
 1287  
     public String getCourseId(){
 1288  0
         return cluProposalModel.<String>get("id");
 1289  
     }
 1290  
 
 1291  
     public String getCourseState(){
 1292  0
         return cluProposalModel.<String>get("state");
 1293  
     }
 1294  
 
 1295  
     public boolean isNew() {
 1296  0
         return isNew;
 1297  
     }
 1298  
 
 1299  
     public CourseRequirementsDataModel getReqDataModel() {
 1300  0
         return reqDataModel;
 1301  
     }
 1302  
 
 1303  
     public CourseRequirementsDataModel getReqDataModelComp() {
 1304  0
         return reqDataModelComp;
 1305  
     }
 1306  
 
 1307  
     @Override
 1308  
     public DataModel getExportDataModel() {
 1309  0
         return cluProposalModel;
 1310  
     }
 1311  
     
 1312  
     /**
 1313  
      * 
 1314  
      * @see org.kuali.student.common.ui.client.reporting.ReportExport#getExportTemplateName()
 1315  
      */
 1316  
     @Override
 1317  
     public String getExportTemplateName() {
 1318  0
         if (LUConstants.PROPOSAL_TYPE_COURSE_CREATE.equals(currentDocType)){
 1319  0
             return "base.template";
 1320  
         }
 1321  0
         return "proposal.template";
 1322  
     }
 1323  
     
 1324  
     @Override
 1325  
     public List<ExportElement> getExportElementsFromView() {
 1326  0
         List<ExportElement> exportElements = new ArrayList<ExportElement>();
 1327  0
         if (this.getCurrentViewEnum().equals(CourseSections.SUMMARY)) {      
 1328  0
             SummaryTableSection tableSection = this.cfg.getSummaryConfigurer().getTableSection();
 1329  0
             ExportElement heading = new ExportElement();
 1330  0
             heading.setFieldLabel("");
 1331  0
             heading.setFieldValue(cluProposalModel.getModelName());
 1332  0
             heading.setFieldValue2(comparisonModel.getModelName());
 1333  0
             exportElements.add(heading);
 1334  0
             exportElements.addAll(ExportUtils.getDetailsForWidget(tableSection.getSummaryTable()));
 1335  
         }
 1336  0
         return exportElements;
 1337  
     }
 1338  
     
 1339  
     @Override
 1340  
     public boolean isExportButtonActive() {
 1341  0
         if (this.getCurrentViewEnum() != null && this.getCurrentViewEnum().equals(CourseSections.SUMMARY)) {   
 1342  0
             return true;
 1343  
         } else {
 1344  0
             return false;
 1345  
         }
 1346  
             
 1347  
     }
 1348  
     
 1349  
     /**
 1350  
      * This method is used to determine which state the dto will be when making the save call. The information
 1351  
      * is used by the metadata service (along with workflow node) to determine the appropriate required indicators
 1352  
      * for field elements.
 1353  
      */
 1354  
     protected String getStateforSaveAction(DataModel model){
 1355  
                 //The state for existing course proposal will be the state set on existing course
 1356  0
             String state = (String)model.get(CreditCourseConstants.STATE);
 1357  
                 
 1358  
             //If null, this means it is a new course proposal, in which case we will default to configurer state
 1359  
             //which should be DRAFT
 1360  0
             if (state == null){
 1361  0
                         state = cfg.getState();
 1362  
                 }
 1363  
             
 1364  0
                 return state;
 1365  
     }
 1366  
     
 1367  
     public String getMessage(String courseMessageKey) {
 1368  0
             String msg = Application.getApplicationContext().getMessage(MSG_GROUP, courseMessageKey);
 1369  0
             if (msg == null) {
 1370  0
                     msg = courseMessageKey;
 1371  
             }
 1372  0
             return msg;
 1373  
     }
 1374  
 
 1375  
     /**
 1376  
      * This method exists to allow the save/get implementations defined in this CourseProposalController
 1377  
      * in this controller to be reused in the CourseAdminWithoutVersion controller. This is in an attempt
 1378  
      * prevent duplication of a large chunk of code in the CourseAdminWithoutVersion controller. Rather than
 1379  
      * have a save wrapped with proposal information, the  CourseAdminWithoutVersion will override this method
 1380  
      * and return the standard course rpc service which does not use filters for proposal data. 
 1381  
      * 
 1382  
      * @return the course rpc service to use
 1383  
      */
 1384  
     
 1385  
     protected  BaseDataOrchestrationRpcServiceAsync getCourseProposalRpcService(){
 1386  0
             return cluProposalRpcServiceAsync;
 1387  
     }
 1388  
     
 1389  
     public CourseProposalConfigurer getCourseProposalConfigurer() {
 1390  0
             return cfg;
 1391  
     }
 1392  
 }