Coverage Report - org.kuali.student.lum.program.client.major.proposal.MajorProposalController
 
Classes in this File Line Coverage Branch Coverage Complexity
MajorProposalController
0%
0/106
0%
0/28
1.857
MajorProposalController$1
0%
0/3
N/A
1.857
MajorProposalController$10
0%
0/11
N/A
1.857
MajorProposalController$11
0%
0/6
N/A
1.857
MajorProposalController$11$1
0%
0/7
0%
0/2
1.857
MajorProposalController$12
0%
0/42
0%
0/8
1.857
MajorProposalController$13
0%
0/6
0%
0/2
1.857
MajorProposalController$14
0%
0/5
0%
0/4
1.857
MajorProposalController$14$1
0%
0/6
N/A
1.857
MajorProposalController$2
0%
0/3
N/A
1.857
MajorProposalController$3
0%
0/6
0%
0/2
1.857
MajorProposalController$4
0%
0/3
N/A
1.857
MajorProposalController$4$1
0%
0/3
N/A
1.857
MajorProposalController$4$1$1
0%
0/11
0%
0/6
1.857
MajorProposalController$4$1$1$1
0%
0/5
0%
0/2
1.857
MajorProposalController$4$1$1$1$1
0%
0/5
0%
0/2
1.857
MajorProposalController$5
0%
0/27
0%
0/10
1.857
MajorProposalController$6
0%
0/9
N/A
1.857
MajorProposalController$7
0%
0/12
0%
0/4
1.857
MajorProposalController$8
0%
0/3
N/A
1.857
MajorProposalController$9
0%
0/4
0%
0/2
1.857
 
 1  
 package org.kuali.student.lum.program.client.major.proposal;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.Iterator;
 5  
 import java.util.List;
 6  
 import java.util.Set;
 7  
 import java.util.TreeSet;
 8  
 
 9  
 import org.kuali.student.common.assembly.data.Data;
 10  
 import org.kuali.student.common.assembly.data.Data.Property;
 11  
 import org.kuali.student.common.assembly.data.QueryPath;
 12  
 import org.kuali.student.common.rice.authorization.PermissionType;
 13  
 import org.kuali.student.common.ui.client.application.Application;
 14  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 15  
 import org.kuali.student.common.ui.client.application.ViewContext;
 16  
 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
 17  
 import org.kuali.student.common.ui.client.mvc.Callback;
 18  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 19  
 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
 20  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 21  
 import org.kuali.student.common.ui.client.mvc.View;
 22  
 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
 23  
 import org.kuali.student.common.ui.client.service.DataSaveResult;
 24  
 import org.kuali.student.common.ui.client.validator.ValidatorClientUtils;
 25  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 26  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract;
 27  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
 28  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
 29  
 import org.kuali.student.common.ui.shared.IdAttributes;
 30  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 31  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 32  
 import org.kuali.student.core.workflow.ui.client.widgets.WorkflowUtilities;
 33  
 import org.kuali.student.lum.common.client.configuration.LUMViews;
 34  
 import org.kuali.student.lum.common.client.helpers.RecentlyViewedHelper;
 35  
 import org.kuali.student.lum.common.client.widgets.AppLocations;
 36  
 import org.kuali.student.lum.program.client.ProgramConstants;
 37  
 import org.kuali.student.lum.program.client.ProgramRegistry;
 38  
 import org.kuali.student.lum.program.client.ProgramSections;
 39  
 import org.kuali.student.lum.program.client.ProgramUtils;
 40  
 import org.kuali.student.lum.program.client.events.AddSpecializationEvent;
 41  
 import org.kuali.student.lum.program.client.events.AfterSaveEvent;
 42  
 import org.kuali.student.lum.program.client.events.ChangeViewEvent;
 43  
 import org.kuali.student.lum.program.client.events.MetadataLoadedEvent;
 44  
 import org.kuali.student.lum.program.client.events.ModelLoadedEvent;
 45  
 import org.kuali.student.lum.program.client.events.SpecializationCreatedEvent;
 46  
 import org.kuali.student.lum.program.client.events.SpecializationSaveEvent;
 47  
 import org.kuali.student.lum.program.client.events.SpecializationUpdateEvent;
 48  
 import org.kuali.student.lum.program.client.events.StateChangeEvent;
 49  
 import org.kuali.student.lum.program.client.events.StoreRequirementIDsEvent;
 50  
 import org.kuali.student.lum.program.client.events.UpdateEvent;
 51  
 import org.kuali.student.lum.program.client.major.MajorController;
 52  
 import org.kuali.student.lum.program.client.properties.ProgramProperties;
 53  
 import org.kuali.student.lum.program.client.rpc.AbstractCallback;
 54  
 import org.kuali.student.lum.program.client.rpc.MajorDisciplineProposalRpcService;
 55  
 import org.kuali.student.lum.program.client.rpc.MajorDisciplineProposalRpcServiceAsync;
 56  
 import org.kuali.student.lum.program.client.rpc.MajorDisciplineRpcServiceAsync;
 57  
 import org.kuali.student.lum.program.client.widgets.ProgramSideBar;
 58  
 
 59  
 import com.google.gwt.core.client.GWT;
 60  
 import com.google.gwt.event.dom.client.ClickEvent;
 61  
 import com.google.gwt.event.dom.client.ClickHandler;
 62  
 import com.google.gwt.event.shared.HandlerManager;
 63  
 import com.google.gwt.user.client.Window;
 64  
 
 65  
 /**
 66  
  * @author Igor
 67  
  */
 68  0
 public class MajorProposalController extends MajorController {
 69  
 
 70  0
     private final KSButton saveButton = new KSButton(ProgramProperties.get().common_save());
 71  0
     private final KSButton cancelButton = new KSButton(ProgramProperties.get().common_cancel(), KSButtonAbstract.ButtonStyle.ANCHOR_LARGE_CENTERED);
 72  0
     private final Set<String> existingVariationIds = new TreeSet<String>();
 73  0
     protected String proposalPath = "";
 74  
     protected WorkflowUtilities workflowUtil; 
 75  
 
 76  
  
 77  
     /**
 78  
      * Constructor.
 79  
      *
 80  
      * @param programModel
 81  
      */
 82  
     public MajorProposalController(DataModel programModel, ViewContext viewContext, HandlerManager eventBus) {
 83  0
         super(programModel, viewContext, eventBus); 
 84  0
         configurer = GWT.create(MajorProposalConfigurer.class);
 85  0
         proposalPath = configurer.getProposalPath();
 86  0
         workflowUtil = new WorkflowUtilities(MajorProposalController.this, proposalPath, "Proposal Actions");//TODO make msg
 87  
         
 88  0
         sideBar.setState(ProgramSideBar.State.EDIT);
 89  0
         initHandlers();
 90  0
     }
 91  
     
 92  
     /**
 93  
      * We need to override the method in MajorDisciplineController
 94  
      * to ensure our custom proposal service is called, which has
 95  
      * the filter needed to pull proposal info out of the model.
 96  
      */
 97  
     @Override
 98  
     protected MajorDisciplineRpcServiceAsync createProgramRemoteService() {
 99  0
         return GWT.create(MajorDisciplineProposalRpcService.class);
 100  
     }
 101  
 
 102  
     @Override
 103  
     protected void configureView() {
 104  0
         super.configureView();
 105  0
         if (!initialized) {
 106  0
             eventBus.fireEvent(new MetadataLoadedEvent(programModel.getDefinition(), this));
 107  0
             List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
 108  0
             excludedViews.add(ProgramSections.PROGRAM_REQUIREMENTS_EDIT);
 109  0
             excludedViews.add(ProgramSections.SUPPORTING_DOCUMENTS_EDIT);
 110  0
             excludedViews.add(ProgramSections.SUMMARY);
 111  0
             addCommonButton(ProgramProperties.get().program_menu_sections(), saveButton, excludedViews);
 112  0
             addCommonButton(ProgramProperties.get().program_menu_sections(), cancelButton, excludedViews);
 113  0
             initialized = true;
 114  
         }
 115  0
     }
 116  
 
 117  
     /**
 118  
      * 
 119  
      * This overridden method is called by the framework to pass request parameters (basically).
 120  
      * <p>
 121  
      * See https://wiki.kuali.org/display/STUDENTDOC/6.4+History%2C+Breadcrumbs+and+ViewContext
 122  
      * <p>
 123  
      * 
 124  
      * @see org.kuali.student.lum.program.client.ProgramController#setViewContext(org.kuali.student.common.ui.client.application.ViewContext)
 125  
      */
 126  
     @Override
 127  
     public void setViewContext(ViewContext viewContext) {
 128  0
         super.setViewContext(viewContext);
 129  0
         if(viewContext.getId() != null && !viewContext.getId().isEmpty()){
 130  0
             if(viewContext.getIdType() != IdType.COPY_OF_OBJECT_ID && viewContext.getIdType() != IdType.COPY_OF_KS_KEW_OBJECT_ID){
 131  
                 
 132  0
                 viewContext.setPermissionType(PermissionType.OPEN);
 133  
             } else{
 134  
                 // Since we are making a copy and we are in the proposal controller we know
 135  
                 // we are submitting a new proposal.  We need to reset the model so that
 136  
                 // work flow utilities reloads it.  This method is called multiple times 
 137  
                 // by the history stack. 
 138  0
                 resetModel();
 139  
                 //they are trying to make a modification
 140  0
                 viewContext.setPermissionType(PermissionType.INITIATE);
 141  
             }
 142  
         }
 143  
         else{
 144  0
             viewContext.setPermissionType(PermissionType.INITIATE);
 145  
         }
 146  0
     }
 147  
 
 148  
     /**
 149  
      * Used by configurer when adding widget to the screen.  Allows
 150  
      * us to get the workflow utilities we initialize in the 
 151  
      * controller. 
 152  
      * @return
 153  
      */
 154  
     public WorkflowUtilities getWfUtilities(){
 155  0
         return workflowUtil;
 156  
     }
 157  
     
 158  
     private void initHandlers() {
 159  0
         saveButton.addClickHandler(new ClickHandler() {
 160  
 
 161  
             @Override
 162  
             public void onClick(ClickEvent event) {
 163  0
                 doSave();
 164  0
             }
 165  
         });
 166  0
         cancelButton.addClickHandler(new ClickHandler() {
 167  
 
 168  
             @Override
 169  
             public void onClick(ClickEvent event) {
 170  0
                 doCancel();
 171  0
             }
 172  
         });
 173  0
         eventBus.addHandler(UpdateEvent.TYPE, new UpdateEvent.Handler() {
 174  
             @Override
 175  
             public void onEvent(UpdateEvent event) {
 176  0
                 Enum<?> view = event.getCurrentView();
 177  0
                 if (view != null) {
 178  0
                     setCurrentViewEnum(view);
 179  
                 }
 180  0
                 doSave(event.getOkCallback());
 181  
 
 182  0
             }
 183  
         });
 184  0
         eventBus.addHandler(StateChangeEvent.TYPE, new StateChangeEvent.Handler() {
 185  
             @Override
 186  
             public void onEvent(final StateChangeEvent event) {
 187  
                     //FIXME: The proper way of doing this would be a single server side call to validate next state
 188  
                     //which would retrieve warnings & required for next state, instead of re-validating warnings for
 189  
                     //current state server side and validating required for next state client side.
 190  0
                     programRemoteService.validate(programModel.getRoot(), new KSAsyncCallback<List<ValidationResultInfo>>(){
 191  
                                         @Override
 192  
                                         public void onSuccess(final List<ValidationResultInfo> currentStateResults) {
 193  0
                                 programModel.validateNextState(new Callback<List<ValidationResultInfo>>() {
 194  
                                     @Override
 195  
                                     public void exec(List<ValidationResultInfo> nextStateResults) {
 196  
                                             //Update validation warnings and process for all screens
 197  0
                                             Application.getApplicationContext().clearValidationWarnings();
 198  0
                                             Application.getApplicationContext().addValidationWarnings(currentStateResults);
 199  0
                                             isValid(Application.getApplicationContext().getValidationWarnings(), false);
 200  
                                         
 201  0
                                             boolean isSectionValid = isValid(nextStateResults, true) 
 202  
                                                 && Application.getApplicationContext().getValidationWarnings().isEmpty();
 203  0
                                         if (isSectionValid) {
 204  0
                                             Callback<Boolean> callback = new Callback<Boolean>() {
 205  
                                                 @Override
 206  
                                                 public void exec(Boolean result) {
 207  0
                                                     if (result) {
 208  0
                                                         reloadMetadata = true;
 209  0
                                                         loadMetadata(new Callback<Boolean>() {
 210  
                                                             @Override
 211  
                                                             public void exec(Boolean result) {
 212  0
                                                                 if (result) {
 213  0
                                                                     ProgramUtils.syncMetadata(configurer, programModel.getDefinition());
 214  0
                                                                     HistoryManager.navigate(AppLocations.Locations.VIEW_PROGRAM.getLocation(), context);
 215  
                                                                 }
 216  0
                                                             }
 217  
                                                         });
 218  
                                                     }
 219  0
                                                 }
 220  
                                             };
 221  0
                                             updateState(event.getProgramStatus().getValue(), callback);
 222  0
                                         } else {
 223  0
                                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 224  
                                         }
 225  0
                                     }
 226  
                                 });
 227  
 
 228  
                                                 
 229  0
                                         }
 230  
                             
 231  
                     });                
 232  0
             }
 233  
         });
 234  
 
 235  0
         eventBus.addHandler(SpecializationSaveEvent.TYPE, new SpecializationSaveEvent.Handler() {
 236  
             @Override
 237  
             public void onEvent(SpecializationSaveEvent event) {
 238  
 
 239  0
                 Data currentVariations = getDataProperty(ProgramConstants.VARIATIONS);
 240  
 
 241  0
                 existingVariationIds.clear();
 242  
 
 243  0
                 for (Data.Property prop : currentVariations) {
 244  0
                     String existingId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 245  0
                     existingVariationIds.add(existingId);
 246  0
                 }
 247  0
                 String updatedId = event.getData().get(ProgramConstants.ID);
 248  0
                 Integer updatedKey = null;
 249  
 
 250  
                 //FIXME: This is ugly but gets us past a  blocker issue. 
 251  
                 // Theres something wrong with the way the models are
 252  
                 // handled in the major and variation controllers  so they get out of sync.
 253  
                 // This is a temporary workaround
 254  0
                 if (updatedId != null) { // this is an update of an existing variation
 255  0
                     for (Data.Property prop : currentVariations) {
 256  0
                         String id = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 257  0
                         if (updatedId.equals(id)) {
 258  0
                             updatedKey = prop.getKey();
 259  0
                             Data currentMetaInfo = ((Data) prop.getValue()).get("metaInfo");
 260  0
                             String latestVersionInd = currentMetaInfo.get("versionInd");
 261  0
                             Data newMetaInfo = event.getData().get("metaInfo");
 262  0
                             if (newMetaInfo == null) {
 263  0
                                 newMetaInfo = new Data();
 264  0
                                 event.getData().set("metaInfo", newMetaInfo);
 265  
                             }
 266  0
                             newMetaInfo.set("versionInd", latestVersionInd);
 267  0
                             break;
 268  
                         }
 269  0
                     }
 270  
 
 271  0
                     currentVariations.set(updatedKey, event.getData());
 272  
                 } else {
 273  0
                     currentVariations.add(event.getData());
 274  
 
 275  
                 }
 276  0
                 doSave();
 277  0
             }
 278  
         });
 279  0
         eventBus.addHandler(AddSpecializationEvent.TYPE, new AddSpecializationEvent.Handler() {
 280  
             @Override
 281  
             public void onEvent(AddSpecializationEvent event) {
 282  0
                 String id = getStringProperty(ProgramConstants.ID);
 283  0
                 ProgramRegistry.setRow((getDataProperty(ProgramConstants.VARIATIONS)).size());
 284  0
                 ProgramRegistry.setData(ProgramUtils.createNewSpecializationBasedOnMajor(programModel));
 285  0
                 ViewContext viewContext = new ViewContext();
 286  0
                 viewContext.setId(id);
 287  0
                 viewContext.setIdType(IdAttributes.IdType.OBJECT_ID);
 288  0
                 HistoryManager.navigate(AppLocations.Locations.EDIT_VARIATION.getLocation(), viewContext);
 289  
 
 290  0
             }
 291  
         });
 292  
 
 293  0
         eventBus.addHandler(StoreRequirementIDsEvent.TYPE, new StoreRequirementIDsEvent.Handler() {
 294  
             @Override
 295  
             public void onEvent(StoreRequirementIDsEvent event) {
 296  0
                 List<String> ids = event.getProgramRequirementIds();
 297  
 
 298  0
                 programModel.set(QueryPath.parse(ProgramConstants.PROGRAM_REQUIREMENTS), new Data());
 299  0
                 Data programRequirements = programModel.get(ProgramConstants.PROGRAM_REQUIREMENTS);
 300  
 
 301  0
                 if (programRequirements == null) {
 302  0
                     Window.alert("Cannot find program requirements in data model.");
 303  0
                     GWT.log("Cannot find program requirements in data model", null);
 304  0
                     return;
 305  
                 }
 306  
 
 307  0
                 for (String id : ids) {
 308  0
                     programRequirements.add(id);
 309  
                 }
 310  0
                 doSave();
 311  0
             }
 312  
         });
 313  0
         eventBus.addHandler(ChangeViewEvent.TYPE, new ChangeViewEvent.Handler() {
 314  
             @Override
 315  
             public void onEvent(ChangeViewEvent event) {
 316  0
                 showView(event.getViewToken());
 317  0
             }
 318  
         });
 319  0
         eventBus.addHandler(ModelLoadedEvent.TYPE, new ModelLoadedEvent.Handler(){
 320  
                         @Override
 321  
                         public void onEvent(ModelLoadedEvent event) {
 322  0
                                 if (workflowUtil != null){
 323  0
                                         workflowUtil.requestAndSetupModel();
 324  
                                 }
 325  0
                         }                
 326  
         });
 327  0
     }
 328  
 
 329  
     @Override
 330  
     protected void loadModel(ModelRequestCallback<DataModel> callback) {
 331  0
         ViewContext viewContext = getViewContext();
 332  0
         if (viewContext.getIdType() == IdType.COPY_OF_OBJECT_ID) {
 333  0
             createNewVersionAndLoadModel(callback, viewContext);
 334  
         } else {
 335  0
             super.loadModel(callback);
 336  
         }
 337  0
     }
 338  
 
 339  
     protected void createNewVersionAndLoadModel(final ModelRequestCallback<DataModel> callback, final ViewContext viewContext) {
 340  0
         Data data = new Data();
 341  
         
 342  
         
 343  0
         Data versionData = new Data();
 344  0
         versionData.set(new Data.StringKey("versionIndId"), getViewContext().getId());
 345  0
         versionData.set(new Data.StringKey("versionComment"), "Major Disicpline Version");
 346  0
         data.set(new Data.StringKey("versionInfo"), versionData);
 347  
 
 348  0
         programRemoteService.saveData(data, new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_retrievingData()) {
 349  
             @Override
 350  
             public void onSuccess(DataSaveResult result) {
 351  0
                 super.onSuccess(result);
 352  0
                 refreshModelAndView(result);
 353  0
                 viewContext.setId(ProgramUtils.getProgramId(programModel));
 354  0
                 viewContext.setIdType(IdType.OBJECT_ID);                
 355  0
                 callback.onModelReady(programModel);
 356  0
                 eventBus.fireEvent(new ModelLoadedEvent(programModel));
 357  0
             }
 358  
 
 359  
             @Override
 360  
             public void onFailure(Throwable caught) {
 361  0
                 super.onFailure(caught);
 362  0
                 callback.onRequestFail(caught);
 363  0
             }
 364  
         });
 365  
 
 366  0
     }
 367  
 
 368  
     private void doSave(final Callback<Boolean> okCallback) {
 369  0
         requestModel(new ModelRequestCallback<DataModel>() {
 370  
             @Override
 371  
             public void onModelReady(DataModel model) {
 372  0
                 MajorProposalController.this.updateModelFromCurrentView();
 373  0
                 model.validate(new Callback<List<ValidationResultInfo>>() {
 374  
                     @Override
 375  
                     public void exec(List<ValidationResultInfo> result) {
 376  0
                         boolean isSectionValid = isValid(result, true);
 377  0
                         if (isSectionValid) {
 378  0
                             saveData(okCallback);
 379  
                         } else {
 380  0
                             okCallback.exec(false);
 381  0
                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 382  
                         }
 383  0
                     }
 384  
                 });
 385  
 
 386  0
             }
 387  
 
 388  
             @Override
 389  
             public void onRequestFail(Throwable cause) {
 390  0
                 GWT.log("Unable to retrieve model for validation and save", cause);
 391  0
             }
 392  
         });
 393  0
     }
 394  
 
 395  
     private void doCancel() {
 396  0
         showView(ProgramSections.SUMMARY);
 397  0
     }
 398  
 
 399  
     @Override
 400  
     protected void doSave() {
 401  0
         doSave(NO_OP_CALLBACK);
 402  0
     }
 403  
 
 404  
     private void saveData(final Callback<Boolean> okCallback) {
 405  0
         programRemoteService.saveData(programModel.getRoot(), new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_savingData()) {
 406  
             @Override
 407  
             public void onSuccess(DataSaveResult result) {
 408  0
                 super.onSuccess(result);
 409  
 
 410  
                 //Clear warning states on field and any warnings stored in ApplicationContext;
 411  0
                 clearAllWarnings();
 412  0
                 Application.getApplicationContext().clearValidationWarnings();
 413  
                 
 414  0
                 List<ValidationResultInfo> validationResults = result.getValidationResults();
 415  0
                 Application.getApplicationContext().addValidationWarnings(validationResults);
 416  0
                 if (ValidatorClientUtils.hasErrors(validationResults)) {
 417  0
                     ProgramUtils.retrofitValidationResults(validationResults);
 418  0
                     isValid(validationResults, false, true);
 419  0
                     ProgramUtils.handleValidationErrorsForSpecializations(validationResults, programModel);
 420  
                     
 421  
                     //Clean up anything created by earlier code
 422  0
                     Data currentVariations = getDataProperty(ProgramConstants.VARIATIONS);
 423  
 
 424  0
                     existingVariationIds.clear();
 425  
 
 426  0
                     for (Iterator<Property> iter = currentVariations.iterator();iter.hasNext();) {
 427  0
                             Property prop = iter.next();
 428  0
                         String existingId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 429  0
                         if(existingId==null){
 430  0
                                 iter.remove();
 431  
                         }else{
 432  0
                                 existingVariationIds.add(existingId);
 433  
                         }
 434  0
                     }
 435  
                     
 436  0
                     okCallback.exec(false);
 437  0
                 } else {
 438  0
                     refreshModelAndView(result);
 439  0
                     resetFieldInteractionFlag();
 440  0
                     configurer.applyPermissions();
 441  0
                     handleSpecializations();
 442  0
                     throwAfterSaveEvent();
 443  0
                     HistoryManager.logHistoryChange();
 444  0
                     ViewContext viewContext = getViewContext();
 445  0
                     viewContext.setId(getStringProperty(ProgramConstants.ID));
 446  0
                     viewContext.setIdType(IdType.OBJECT_ID);
 447  
 
 448  0
                                     if (ValidatorClientUtils.hasWarnings(validationResults)){
 449  
                                             //Show validation warnings for major
 450  0
                                             isValid(result.getValidationResults(), false, true);                                            
 451  0
                                             KSNotifier.show("Saved with Warnings");
 452  
                                     } else {
 453  0
                         KSNotifier.show(ProgramProperties.get().common_successfulSave());
 454  
                                     }                                  
 455  
                     
 456  
                     // add to recently viewed now that we're sure to know the program's id
 457  0
                     ViewContext docContext = new ViewContext();
 458  0
                     docContext.setId(getStringProperty(ProgramConstants.ID));
 459  0
                     docContext.setIdType(IdType.OBJECT_ID);
 460  0
                     docContext.setAttribute(ProgramConstants.TYPE, ProgramConstants.MAJOR_LU_TYPE_ID + '/' + ProgramSections.PROGRAM_DETAILS_VIEW);
 461  0
                     RecentlyViewedHelper.addDocument(getProgramName(),
 462  
                             HistoryManager.appendContext(AppLocations.Locations.VIEW_PROGRAM.getLocation(), docContext));
 463  
                    
 464  0
                     okCallback.exec(true);
 465  0
                     processCurrentView();
 466  
                 }
 467  0
             }
 468  
         });
 469  0
     }
 470  
 
 471  
     private void processCurrentView() {
 472  0
         Enum<?> currentView = getCurrentViewEnum();
 473  0
         if (currentView.name().equals(ProgramSections.VIEW_ALL.name())) {
 474  0
             HistoryManager.navigate(AppLocations.Locations.VIEW_PROGRAM.getLocation(), getViewContext());
 475  
         } else {
 476  0
             showView(currentView);
 477  
         }
 478  0
     }
 479  
 
 480  
     /**
 481  
      * Handles after save work for specializations.
 482  
      */
 483  
     private void handleSpecializations() {
 484  0
         String newVariationId = null;
 485  0
         Data variations = programModel.get(ProgramConstants.VARIATIONS);
 486  0
         for (Data.Property prop : variations) {
 487  0
             String varId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 488  0
             if (!existingVariationIds.contains(varId)) {
 489  0
                 newVariationId = varId;
 490  0
                 existingVariationIds.add(newVariationId);
 491  0
                 break;
 492  
             }
 493  0
         }
 494  0
         if (newVariationId != null) {
 495  0
             eventBus.fireEvent(new SpecializationCreatedEvent(newVariationId));
 496  
         } else {
 497  0
             eventBus.fireEvent(new SpecializationUpdateEvent(variations));
 498  
         }
 499  0
     }
 500  
 
 501  
     private void throwAfterSaveEvent() {
 502  0
         eventBus.fireEvent(new AfterSaveEvent(programModel, this));
 503  0
     }
 504  
 
 505  
     @Override
 506  
     public void onModelLoadedEvent() {
 507  0
         Enum<?> changeSection = ProgramRegistry.getSection();
 508  0
         if (changeSection != null) {
 509  0
             showView(changeSection);
 510  0
             ProgramRegistry.setSection(null);
 511  
         } else {
 512  0
             String id = getStringProperty(ProgramConstants.ID);
 513  0
             if (id == null) {
 514  0
                 showView(ProgramSections.PROGRAM_DETAILS_EDIT);
 515  
             } else {
 516  0
                 showView(ProgramSections.SUMMARY);
 517  
             }
 518  
         }
 519  
 
 520  0
     }
 521  
 
 522  
         @Override
 523  
         public void beforeShow(final Callback<Boolean> onReadyCallback) {
 524  0
                 if(!initialized){
 525  0
                         Application.getApplicationContext().clearCrossConstraintMap(null);
 526  0
                         Application.getApplicationContext().clearPathToFieldMapping(null);
 527  
                 }
 528  
                 //Clear the parent path again
 529  0
                 Application.getApplicationContext().setParentPath("");
 530  0
                 super.beforeShow(onReadyCallback);                                                
 531  0
         }
 532  
 
 533  
         //Before show is called before the model is bound to the widgets. We need to update cross constraints after widget binding
 534  
         //This gets called twice which is not optimal
 535  
         @Override
 536  
         public <V extends Enum<?>> void showView(V viewType,
 537  
                         final Callback<Boolean> onReadyCallback) {
 538  0
                 Callback<Boolean> updateCrossConstraintsCallback = new Callback<Boolean>(){
 539  
                         public void exec(Boolean result) {
 540  0
                                 onReadyCallback.exec(result);
 541  0
                         for(HasCrossConstraints crossConstraint:Application.getApplicationContext().getCrossConstraints(null)){
 542  0
                                 crossConstraint.reprocessWithUpdatedConstraints();
 543  
                         }
 544  0
                         showWarnings();        
 545  0
                         }
 546  
         };
 547  0
                 super.showView(viewType, updateCrossConstraintsCallback);
 548  0
         }
 549  
 
 550  
         //Ensure that the managing bodies section view is updated before the user edits specializations
 551  
         @Override
 552  
         public void beforeViewChange(Enum<?> viewChangingTo, final Callback<Boolean> okToChangeCallback){
 553  0
                 if(LUMViews.VARIATION_EDIT.equals(viewChangingTo)){
 554  0
                         getView(ProgramSections.MANAGE_BODIES_EDIT, new Callback<View>(){
 555  
                                 @Override
 556  
                                 public void exec(final View view) {
 557  0
                                         if(view!=null && view instanceof SectionView){
 558  0
                                                 requestModel(new ModelRequestCallback<DataModel>(){
 559  
                                                         public void onModelReady(DataModel model) {
 560  0
                                                                 ((SectionView)view).updateWidgetData(model);
 561  0
                                                                 okToChangeCallback.exec(true);
 562  0
                                                         }
 563  
                                                         public void onRequestFail(Throwable cause) {
 564  0
                                                                 okToChangeCallback.exec(false);
 565  0
                                                         }
 566  
                                                 });
 567  
                                         }else{
 568  0
                                                 okToChangeCallback.exec(true);
 569  
                                         }
 570  0
                                 }});
 571  
                 }else{
 572  0
                         okToChangeCallback.exec(true);
 573  
                 }
 574  0
                 this.showExport(isExportButtonActive());        // KSLAB-1916
 575  0
         }
 576  
 }