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