Coverage Report - org.kuali.student.lum.program.client.major.edit.MajorEditController
 
Classes in this File Line Coverage Branch Coverage Complexity
MajorEditController
0%
0/123
0%
0/28
1.758
MajorEditController$1
0%
0/3
N/A
1.758
MajorEditController$10
0%
0/11
N/A
1.758
MajorEditController$11
0%
0/5
N/A
1.758
MajorEditController$11$1
0%
0/8
N/A
1.758
MajorEditController$11$1$1
0%
0/4
0%
0/2
1.758
MajorEditController$11$1$1$1
0%
0/4
0%
0/2
1.758
MajorEditController$12
0%
0/5
N/A
1.758
MajorEditController$12$1
0%
0/8
N/A
1.758
MajorEditController$12$1$1
0%
0/4
0%
0/2
1.758
MajorEditController$12$1$1$1
0%
0/4
0%
0/2
1.758
MajorEditController$13
0%
0/11
N/A
1.758
MajorEditController$14
0%
0/6
N/A
1.758
MajorEditController$14$1
0%
0/7
0%
0/2
1.758
MajorEditController$15
0%
0/43
0%
0/8
1.758
MajorEditController$16
0%
0/6
0%
0/2
1.758
MajorEditController$17
0%
0/6
0%
0/4
1.758
MajorEditController$17$1
0%
0/5
0%
0/4
1.758
MajorEditController$17$1$1
0%
0/6
N/A
1.758
MajorEditController$2
0%
0/3
N/A
1.758
MajorEditController$3
0%
0/6
0%
0/2
1.758
MajorEditController$4
0%
0/3
N/A
1.758
MajorEditController$4$1
0%
0/3
N/A
1.758
MajorEditController$4$1$1
0%
0/11
0%
0/6
1.758
MajorEditController$4$1$1$1
0%
0/6
0%
0/2
1.758
MajorEditController$4$1$1$1$1
0%
0/5
0%
0/2
1.758
MajorEditController$5
0%
0/27
0%
0/10
1.758
MajorEditController$6
0%
0/9
N/A
1.758
MajorEditController$7
0%
0/16
0%
0/8
1.758
MajorEditController$7$1
0%
0/3
N/A
1.758
MajorEditController$7$1$1
0%
0/10
0%
0/2
1.758
MajorEditController$7$1$1$1
0%
0/2
N/A
1.758
MajorEditController$8
0%
0/3
N/A
1.758
MajorEditController$9
0%
0/5
0%
0/6
1.758
 
 1  
 package org.kuali.student.lum.program.client.major.edit;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.HashMap;
 5  
 import java.util.Iterator;
 6  
 import java.util.List;
 7  
 import java.util.Map;
 8  
 import java.util.Set;
 9  
 import java.util.TreeSet;
 10  
 
 11  
 import org.kuali.student.common.assembly.data.Data;
 12  
 import org.kuali.student.common.assembly.data.Data.Property;
 13  
 import org.kuali.student.common.assembly.data.Metadata;
 14  
 import org.kuali.student.common.assembly.data.QueryPath;
 15  
 import org.kuali.student.common.dto.DtoConstants;
 16  
 import org.kuali.student.common.ui.client.application.Application;
 17  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 18  
 import org.kuali.student.common.ui.client.application.ViewContext;
 19  
 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
 20  
 import org.kuali.student.common.ui.client.mvc.Callback;
 21  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 22  
 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
 23  
 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
 24  
 import org.kuali.student.common.ui.client.mvc.ModelProvider;
 25  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 26  
 import org.kuali.student.common.ui.client.mvc.View;
 27  
 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
 28  
 import org.kuali.student.common.ui.client.service.DataSaveResult;
 29  
 import org.kuali.student.common.ui.client.validator.ValidatorClientUtils;
 30  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 31  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract;
 32  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
 33  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
 34  
 import org.kuali.student.common.ui.shared.IdAttributes;
 35  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 36  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 37  
 import org.kuali.student.lum.common.client.configuration.LUMViews;
 38  
 import org.kuali.student.lum.common.client.helpers.RecentlyViewedHelper;
 39  
 import org.kuali.student.lum.common.client.widgets.AppLocations;
 40  
 import org.kuali.student.lum.program.client.ProgramConstants;
 41  
 import org.kuali.student.lum.program.client.ProgramRegistry;
 42  
 import org.kuali.student.lum.program.client.ProgramSections;
 43  
 import org.kuali.student.lum.program.client.ProgramStatus;
 44  
 import org.kuali.student.lum.program.client.ProgramUtils;
 45  
 import org.kuali.student.lum.program.client.events.AddSpecializationEvent;
 46  
 import org.kuali.student.lum.program.client.events.AfterSaveEvent;
 47  
 import org.kuali.student.lum.program.client.events.ChangeViewEvent;
 48  
 import org.kuali.student.lum.program.client.events.MetadataLoadedEvent;
 49  
 import org.kuali.student.lum.program.client.events.ModelLoadedEvent;
 50  
 import org.kuali.student.lum.program.client.events.SpecializationCreatedEvent;
 51  
 import org.kuali.student.lum.program.client.events.SpecializationSaveEvent;
 52  
 import org.kuali.student.lum.program.client.events.SpecializationUpdateEvent;
 53  
 import org.kuali.student.lum.program.client.events.StateChangeEvent;
 54  
 import org.kuali.student.lum.program.client.events.StoreRequirementIDsEvent;
 55  
 import org.kuali.student.lum.program.client.events.UpdateEvent;
 56  
 import org.kuali.student.lum.program.client.major.MajorController;
 57  
 import org.kuali.student.lum.program.client.properties.ProgramProperties;
 58  
 import org.kuali.student.lum.program.client.requirements.ProgramRequirementsDataModel;
 59  
 import org.kuali.student.lum.program.client.rpc.AbstractCallback;
 60  
 import org.kuali.student.lum.program.client.widgets.ProgramSideBar;
 61  
 
 62  
 import com.google.gwt.core.client.GWT;
 63  
 import com.google.gwt.event.dom.client.ClickEvent;
 64  
 import com.google.gwt.event.dom.client.ClickHandler;
 65  
 import com.google.gwt.event.shared.HandlerManager;
 66  
 import com.google.gwt.user.client.Window;
 67  
 
 68  
 /**
 69  
  * @author Igor
 70  
  */
 71  0
 public class MajorEditController extends MajorController {
 72  
 
 73  0
     private final KSButton saveButton = new KSButton(ProgramProperties.get().common_save());
 74  0
     private final KSButton cancelButton = new KSButton(ProgramProperties.get().common_cancel(), KSButtonAbstract.ButtonStyle.ANCHOR_LARGE_CENTERED);
 75  0
     private final Set<String> existingVariationIds = new TreeSet<String>();
 76  
 
 77  0
         protected final DataModel comparisonModel = new DataModel("Original Program");
 78  0
         private String comparisonModelId = "ComparisonModel";
 79  
          
 80  
     private ProgramRequirementsDataModel reqDataModel;
 81  
     private ProgramRequirementsDataModel reqDataModelComp;
 82  
 
 83  
     /**
 84  
      * Constructor.
 85  
      *
 86  
      * @param programModel
 87  
      */
 88  
     public MajorEditController(DataModel programModel, ViewContext viewContext, HandlerManager eventBus) {
 89  0
         super(programModel, viewContext, eventBus);
 90  0
         programModel.setModelName("New Program");
 91  0
         initializeComparisonModel();
 92  0
         configurer = GWT.create(MajorEditConfigurer.class);
 93  0
         sideBar.setState(ProgramSideBar.State.EDIT);
 94  0
         initHandlers();
 95  
 
 96  0
         reqDataModel = new ProgramRequirementsDataModel(eventBus);
 97  0
         reqDataModelComp = new ProgramRequirementsDataModel(eventBus);
 98  0
     }
 99  
 
 100  
     @Override
 101  
     protected void configureView() {
 102  0
         super.configureView();
 103  0
         if (!initialized) {
 104  0
             eventBus.fireEvent(new MetadataLoadedEvent(programModel.getDefinition(), this));
 105  0
             List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
 106  0
             excludedViews.add(ProgramSections.PROGRAM_REQUIREMENTS_EDIT);
 107  0
             excludedViews.add(ProgramSections.SUPPORTING_DOCUMENTS_EDIT);
 108  0
             excludedViews.add(ProgramSections.SUMMARY);
 109  0
             addCommonButton(ProgramProperties.get().program_menu_sections(), saveButton, excludedViews);
 110  0
             addCommonButton(ProgramProperties.get().program_menu_sections(), cancelButton, excludedViews);
 111  0
             initialized = true;
 112  
         }
 113  0
     }
 114  
 
 115  
     private void initHandlers() {
 116  0
         saveButton.addClickHandler(new ClickHandler() {
 117  
 
 118  
             @Override
 119  
             public void onClick(ClickEvent event) {
 120  0
                 doSave();
 121  0
             }
 122  
         });
 123  0
         cancelButton.addClickHandler(new ClickHandler() {
 124  
 
 125  
             @Override
 126  
             public void onClick(ClickEvent event) {
 127  0
                 doCancel();
 128  0
             }
 129  
         });
 130  0
         eventBus.addHandler(UpdateEvent.TYPE, new UpdateEvent.Handler() {
 131  
             @Override
 132  
             public void onEvent(UpdateEvent event) {
 133  0
                 Enum<?> view = event.getCurrentView();
 134  0
                 if (view != null) {
 135  0
                     setCurrentViewEnum(view);
 136  
                 }
 137  0
                 doSave(event.getOkCallback());
 138  
 
 139  0
             }
 140  
         });
 141  0
         eventBus.addHandler(StateChangeEvent.TYPE, new StateChangeEvent.Handler() {
 142  
             @Override
 143  
             public void onEvent(final StateChangeEvent event) {
 144  
                     //FIXME: The proper way of doing this would be a single server side call to validate next state
 145  
                     //which would retrieve warnings & required for next state, instead of re-validating warnings for
 146  
                     //current state server side and validating required for next state client side.
 147  0
                     programRemoteService.validate(programModel.getRoot(), new KSAsyncCallback<List<ValidationResultInfo>>(){
 148  
                                         @Override
 149  
                                         public void onSuccess(final List<ValidationResultInfo> currentStateResults) {
 150  0
                                 programModel.validateNextState(new Callback<List<ValidationResultInfo>>() {
 151  
                                     @Override
 152  
                                     public void exec(List<ValidationResultInfo> nextStateResults) {
 153  
                                             //Update validation warnings and process for all screens
 154  0
                                             Application.getApplicationContext().clearValidationWarnings();
 155  0
                                             Application.getApplicationContext().addValidationWarnings(currentStateResults);
 156  0
                                             isValid(Application.getApplicationContext().getValidationWarnings(), false);
 157  
                                         
 158  0
                                             boolean isSectionValid = isValid(nextStateResults, true) 
 159  
                                                 && Application.getApplicationContext().getValidationWarnings().isEmpty();
 160  0
                                         if (isSectionValid) {
 161  0
                                             Callback<Boolean> callback = new Callback<Boolean>() {
 162  
                                                 @Override
 163  
                                                 public void exec(Boolean result) {
 164  0
                                                     if (result) {
 165  0
                                                         reloadMetadata = true;
 166  0
                                                         loadMetadata(new Callback<Boolean>() {
 167  
                                                             @Override
 168  
                                                             public void exec(Boolean result) {
 169  0
                                                                 if (result) {
 170  0
                                                                     ProgramUtils.syncMetadata(configurer, programModel.getDefinition());
 171  0
                                                                     HistoryManager.navigate(AppLocations.Locations.VIEW_PROGRAM.getLocation(), context);
 172  
                                                                 }
 173  0
                                                             }
 174  
                                                         });
 175  
                                                     }else{
 176  0
                                                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 177  
                                                     }
 178  0
                                                 }
 179  
                                             };
 180  0
                                             updateState(event.getProgramStatus().getValue(), callback);
 181  0
                                         } else {
 182  0
                                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 183  
                                         }
 184  0
                                     }
 185  
                                 });
 186  
 
 187  
                                                 
 188  0
                                         }
 189  
                             
 190  
                     });                
 191  0
             }
 192  
         });
 193  
 
 194  0
         eventBus.addHandler(SpecializationSaveEvent.TYPE, new SpecializationSaveEvent.Handler() {
 195  
             @Override
 196  
             public void onEvent(SpecializationSaveEvent event) {
 197  
 
 198  0
                 Data currentVariations = getDataProperty(ProgramConstants.VARIATIONS);
 199  
 
 200  0
                 existingVariationIds.clear();
 201  
 
 202  0
                 for (Data.Property prop : currentVariations) {
 203  0
                     String existingId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 204  0
                     existingVariationIds.add(existingId);
 205  0
                 }
 206  0
                 String updatedId = event.getData().get(ProgramConstants.ID);
 207  0
                 Integer updatedKey = null;
 208  
 
 209  
                 //FIXME: This is ugly but gets us past a  blocker issue. 
 210  
                 // Theres something wrong with the way the models are
 211  
                 // handled in the major and variation controllers  so they get out of sync.
 212  
                 // This is a temporary workaround
 213  0
                 if (updatedId != null) { // this is an update of an existing variation
 214  0
                     for (Data.Property prop : currentVariations) {
 215  0
                         String id = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 216  0
                         if (updatedId.equals(id)) {
 217  0
                             updatedKey = prop.getKey();
 218  0
                             Data currentMetaInfo = ((Data) prop.getValue()).get("metaInfo");
 219  0
                             String latestVersionInd = currentMetaInfo.get("versionInd");
 220  0
                             Data newMetaInfo = event.getData().get("metaInfo");
 221  0
                             if (newMetaInfo == null) {
 222  0
                                 newMetaInfo = new Data();
 223  0
                                 event.getData().set("metaInfo", newMetaInfo);
 224  
                             }
 225  0
                             newMetaInfo.set("versionInd", latestVersionInd);
 226  0
                             break;
 227  
                         }
 228  0
                     }
 229  
 
 230  0
                     currentVariations.set(updatedKey, event.getData());
 231  
                 } else {
 232  0
                     currentVariations.add(event.getData());
 233  
 
 234  
                 }
 235  0
                 doSave();
 236  0
             }
 237  
         });
 238  0
         eventBus.addHandler(AddSpecializationEvent.TYPE, new AddSpecializationEvent.Handler() {
 239  
             @Override
 240  
             public void onEvent(AddSpecializationEvent event) {
 241  0
                 String id = getStringProperty(ProgramConstants.ID);
 242  0
                 ProgramRegistry.setRow((getDataProperty(ProgramConstants.VARIATIONS)).size());
 243  0
                 ProgramRegistry.setData(ProgramUtils.createNewSpecializationBasedOnMajor(programModel));
 244  0
                 ViewContext viewContext = new ViewContext();
 245  0
                 viewContext.setId(id);
 246  0
                 viewContext.setIdType(IdAttributes.IdType.OBJECT_ID);
 247  0
                 HistoryManager.navigate(AppLocations.Locations.EDIT_VARIATION.getLocation(), viewContext);
 248  
 
 249  0
             }
 250  
         });
 251  
 
 252  0
         eventBus.addHandler(StoreRequirementIDsEvent.TYPE, new StoreRequirementIDsEvent.Handler() {
 253  
             @Override
 254  
             public void onEvent(StoreRequirementIDsEvent event) {
 255  0
                 List<String> ids = event.getProgramRequirementIds();
 256  
 
 257  0
                 programModel.set(QueryPath.parse(ProgramConstants.PROGRAM_REQUIREMENTS), new Data());
 258  0
                 Data programRequirements = programModel.get(ProgramConstants.PROGRAM_REQUIREMENTS);
 259  
 
 260  0
                 if (programRequirements == null) {
 261  0
                     Window.alert("Cannot find program requirements in data model.");
 262  0
                     GWT.log("Cannot find program requirements in data model", null);
 263  0
                     return;
 264  
                 }
 265  
 
 266  0
                 for (String id : ids) {
 267  0
                     programRequirements.add(id);
 268  
                 }
 269  
                 
 270  0
                     if (getViewContext().getIdType() == IdType.COPY_OF_OBJECT_ID || getViewContext().getIdType() == IdType.OBJECT_ID)        
 271  
                 {
 272  0
                             Callback<Boolean> reqCallback = new Callback<Boolean>() {
 273  
                                     @Override
 274  
                                     public void exec(Boolean result) {
 275  0
                                    programRemoteService.getData(getViewContext().getId(), new AbstractCallback<Data>(ProgramProperties.get().common_retrievingData()) {
 276  
 
 277  
                                         @Override
 278  
                                         public void onFailure(Throwable caught) {
 279  0
                                                 super.onFailure(caught);
 280  0
                                         }
 281  
 
 282  
                                         @Override
 283  
                                         public void onSuccess(Data result) {
 284  0
                                                 super.onSuccess(result);
 285  0
                                                 if (result != null) {
 286  0
                                                         programModel.setRoot(result);
 287  
                                                 }
 288  0
                                                 setHeaderTitle();
 289  0
                                                 setStatus();
 290  0
                                                 reqDataModel.retrieveProgramRequirements(MajorEditController.this, ProgramConstants.PROGRAM_MODEL_ID, new Callback<Boolean>() {
 291  
                                                         @Override
 292  0
                                                         public void exec(Boolean result) {}
 293  
                                                 });                    
 294  0
                                         }
 295  
                                 });
 296  0
                                     }
 297  
                             };
 298  
                         
 299  0
                             doSave(reqCallback); 
 300  0
                     } 
 301  
                     else
 302  0
                             doSave();                
 303  0
             }
 304  
         });
 305  0
         eventBus.addHandler(ChangeViewEvent.TYPE, new ChangeViewEvent.Handler() {
 306  
             @Override
 307  
             public void onEvent(ChangeViewEvent event) {
 308  0
                 showView(event.getViewToken());
 309  0
             }
 310  
         });        
 311  0
     }
 312  
 
 313  
     /**
 314  
      * Initialized comparison model of the controller.
 315  
      */
 316  
     private void initializeComparisonModel() {
 317  0
         super.registerModel(comparisonModelId, new ModelProvider<DataModel>() {
 318  
             @Override
 319  
             public void requestModel(final ModelRequestCallback<DataModel> callback) {
 320  0
                     if(comparisonModel.getRoot() != null && comparisonModel.getRoot().size() != 0 && getViewContext() != null){
 321  0
                             callback.onModelReady(comparisonModel);                            
 322  
                     }
 323  
                     else{
 324  0
                             callback.onModelReady(null);
 325  
                     }                
 326  0
              }
 327  
         });
 328  0
     }
 329  
 
 330  
     @Override
 331  
     protected void loadMetadata(final Callback<Boolean> onReadyCallback) {
 332  0
         Map<String, String> idAttributes = new HashMap<String, String>();
 333  0
         ViewContext viewContext = getViewContext();
 334  0
         IdType idType = viewContext.getIdType();
 335  0
         String viewContextId = null;
 336  0
         if (idType != null) {
 337  0
             idAttributes.put(IdAttributes.ID_TYPE, idType.toString());
 338  0
             viewContextId = viewContext.getId();
 339  0
             if (idType == IdType.COPY_OF_OBJECT_ID) {
 340  0
                 viewContextId = null;
 341  
             }
 342  
         }
 343  0
         if (programModel.getRoot() != null) {
 344  0
             ProgramStatus programStatus = ProgramStatus.of(programModel);
 345  0
             idAttributes.put(DtoConstants.DTO_STATE, programStatus.getValue());
 346  0
             if (programStatus.getNextStatus() != null) {
 347  0
                 idAttributes.put(DtoConstants.DTO_NEXT_STATE, programStatus.getNextStatus().getValue());
 348  
             }
 349  
         }
 350  0
         programRemoteService.getMetadata(viewContextId, idAttributes, new AbstractCallback<Metadata>() {
 351  
 
 352  
             @Override
 353  
             public void onSuccess(Metadata result) {
 354  0
                 super.onSuccess(result);
 355  0
                 DataModelDefinition def = new DataModelDefinition(result);
 356  0
                 programModel.setDefinition(def);
 357  0
                 comparisonModel.setDefinition(def);
 358  0
                 lastLoadedStatus = ProgramStatus.of(programModel);
 359  0
                 afterMetadataLoaded(onReadyCallback);
 360  0
             }
 361  
 
 362  
             @Override
 363  
             public void onFailure(Throwable caught) {
 364  0
                 super.onFailure(caught);
 365  0
                 onReadyCallback.exec(false);
 366  0
             }
 367  
         });
 368  0
     }
 369  
 
 370  
     @Override
 371  
     protected void loadModel(final ModelRequestCallback<DataModel> callback) {            
 372  0
             ViewContext viewContext = getViewContext();
 373  0
         if (viewContext.getIdType() == IdType.COPY_OF_OBJECT_ID) 
 374  
         {        
 375  0
                 ModelRequestCallback<DataModel> comparisonModelCallback = new ModelRequestCallback<DataModel>() {
 376  
                             @Override
 377  
                             public void onModelReady(DataModel model) {
 378  0
                                     programRemoteService.getData(getViewContext().getId(), new AbstractCallback<Data>(ProgramProperties.get().common_retrievingData()) {
 379  
                         @Override
 380  
                         public void onSuccess(Data result) {
 381  0
                             super.onSuccess(result);
 382  0
                             comparisonModel.setRoot(result);
 383  0
                             reqDataModel.retrieveProgramRequirements(MajorEditController.this, ProgramConstants.PROGRAM_MODEL_ID, new Callback<Boolean>() {
 384  
                                 @Override
 385  
                                 public void exec(Boolean result) {
 386  0
                                     if (result) {
 387  0
                                             reqDataModelComp.retrieveProgramRequirements(MajorEditController.this, comparisonModelId, new Callback<Boolean>() {
 388  
                                             @Override
 389  
                                             public void exec(Boolean result) {
 390  0
                                                 if (result) {
 391  0
                                                     callback.onModelReady(comparisonModel);
 392  
                                                 }
 393  0
                                             }
 394  
                                         });
 395  
                                     }
 396  0
                                 }
 397  
                             });                    
 398  0
                         }
 399  
                         
 400  
                         @Override
 401  
                         public void onFailure(Throwable caught) {
 402  0
                             super.onFailure(caught);
 403  0
                             callback.onRequestFail(caught);
 404  0
                         }
 405  
                     });
 406  0
                         }
 407  
 
 408  
                             @Override
 409  
                             public void onRequestFail(Throwable cause) {
 410  0
                     GWT.log("Unable to retrieve comparison model", cause);
 411  0
                             }
 412  
                 };        
 413  
                 
 414  0
                            createNewVersionAndLoadModel(comparisonModelCallback, viewContext);                           
 415  0
         }        
 416  0
         else if (viewContext.getIdType() == IdType.OBJECT_ID)
 417  
         {
 418  0
                 ModelRequestCallback<DataModel> comparisonModelCallback = new ModelRequestCallback<DataModel>() {
 419  
                             @Override
 420  
                             public void onModelReady(DataModel model) {
 421  0
                     programRemoteService.getData(getViewContext().getId(), new AbstractCallback<Data>(ProgramProperties.get().common_retrievingData()) {
 422  
 
 423  
                         @Override
 424  
                         public void onFailure(Throwable caught) {
 425  0
                             super.onFailure(caught);
 426  0
                             callback.onRequestFail(caught);
 427  0
                         }
 428  
 
 429  
                         @Override
 430  
                         public void onSuccess(Data result) {
 431  0
                             super.onSuccess(result);
 432  0
                             comparisonModel.setRoot(result);
 433  0
                             reqDataModel.retrieveProgramRequirements(MajorEditController.this, ProgramConstants.PROGRAM_MODEL_ID, new Callback<Boolean>() {
 434  
                                 @Override
 435  
                                 public void exec(Boolean result) {
 436  0
                                     if (result) {
 437  0
                                             reqDataModelComp.retrieveProgramRequirements(MajorEditController.this, comparisonModelId, new Callback<Boolean>() {
 438  
                                             @Override
 439  
                                             public void exec(Boolean result) {
 440  0
                                                 if (result) {
 441  0
                                                     callback.onModelReady(comparisonModel);
 442  
                                                 }
 443  0
                                             }
 444  
                                         });
 445  
                                     }
 446  0
                                 }
 447  
                             });                    
 448  0
                         }
 449  
                     });
 450  0
                         }
 451  
 
 452  
                             @Override
 453  
                             public void onRequestFail(Throwable cause) {
 454  0
                     GWT.log("Unable to retrieve comparison model", cause);
 455  0
                             }
 456  
                 };        
 457  
                                 
 458  0
                 super.loadModel(comparisonModelCallback);
 459  0
         } else
 460  0
                 super.loadModel(callback);
 461  0
     }
 462  
 
 463  
     protected void createNewVersionAndLoadModel(final ModelRequestCallback<DataModel> callback, final ViewContext viewContext) {
 464  0
         Data data = new Data();
 465  0
         Data versionData = new Data();
 466  0
         versionData.set(new Data.StringKey("versionIndId"), getViewContext().getId());
 467  0
         versionData.set(new Data.StringKey("versionComment"), "Major Disicpline Version");
 468  0
         data.set(new Data.StringKey("versionInfo"), versionData);
 469  
 
 470  0
         programRemoteService.saveData(data, new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_retrievingData()) {
 471  
             @Override
 472  
             public void onSuccess(DataSaveResult result) {
 473  0
                 super.onSuccess(result);
 474  0
                 refreshModelAndView(result);
 475  0
                 viewContext.setId(ProgramUtils.getProgramId(programModel));
 476  0
                 viewContext.setIdType(IdType.OBJECT_ID);                
 477  0
                 callback.onModelReady(programModel);
 478  0
                 eventBus.fireEvent(new ModelLoadedEvent(programModel));
 479  0
             }
 480  
 
 481  
             @Override
 482  
             public void onFailure(Throwable caught) {
 483  0
                 super.onFailure(caught);
 484  0
                 callback.onRequestFail(caught);
 485  0
             }
 486  
         });
 487  
 
 488  0
     }
 489  
 
 490  
     private void doSave(final Callback<Boolean> okCallback) {
 491  0
         requestModel(new ModelRequestCallback<DataModel>() {
 492  
             @Override
 493  
             public void onModelReady(DataModel model) {
 494  0
                 MajorEditController.this.updateModelFromCurrentView();
 495  0
                 model.validate(new Callback<List<ValidationResultInfo>>() {
 496  
                     @Override
 497  
                     public void exec(List<ValidationResultInfo> result) {
 498  0
                         boolean isSectionValid = isValid(result, true);
 499  0
                         if (isSectionValid) {
 500  0
                             saveData(okCallback);
 501  
                         } else {
 502  0
                             okCallback.exec(false);
 503  0
                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
 504  
                         }
 505  0
                     }
 506  
                 });
 507  
 
 508  0
             }
 509  
 
 510  
             @Override
 511  
             public void onRequestFail(Throwable cause) {
 512  0
                 GWT.log("Unable to retrieve model for validation and save", cause);
 513  0
             }
 514  
         });
 515  0
     }
 516  
 
 517  
     private void doCancel() {
 518  0
         Application.navigate(AppLocations.Locations.CURRICULUM_MANAGEMENT.getLocation());
 519  0
     }
 520  
 
 521  
     @Override
 522  
     protected void doSave() {
 523  0
         doSave(NO_OP_CALLBACK);
 524  0
     }
 525  
 
 526  
     private void saveData(final Callback<Boolean> okCallback) {
 527  0
         programRemoteService.saveData(programModel.getRoot(), new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_savingData()) {
 528  
             @Override
 529  
             public void onSuccess(DataSaveResult result) {
 530  0
                 super.onSuccess(result);
 531  
 
 532  
                 //Clear warning states on field and any warnings stored in ApplicationContext;
 533  0
                 clearAllWarnings();
 534  0
                 Application.getApplicationContext().clearValidationWarnings();
 535  
                 
 536  0
                 List<ValidationResultInfo> validationResults = result.getValidationResults();
 537  0
                 Application.getApplicationContext().addValidationWarnings(validationResults);
 538  0
                 if (ValidatorClientUtils.hasErrors(validationResults)) {
 539  0
                     ProgramUtils.retrofitValidationResults(validationResults);
 540  0
                     isValid(validationResults, false, true);
 541  0
                     ProgramUtils.handleValidationErrorsForSpecializations(validationResults, programModel);
 542  
                     
 543  
                     //Clean up anything created by earlier code
 544  0
                     Data currentVariations = getDataProperty(ProgramConstants.VARIATIONS);
 545  
 
 546  0
                     existingVariationIds.clear();
 547  
 
 548  0
                     for (Iterator<Property> iter = currentVariations.iterator();iter.hasNext();) {
 549  0
                             Property prop = iter.next();
 550  0
                         String existingId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 551  0
                         if(existingId==null){
 552  0
                                 iter.remove();
 553  
                         }else{
 554  0
                                 existingVariationIds.add(existingId);
 555  
                         }
 556  0
                     }
 557  
                     // TODO: Error message are being sent back from the server but we 
 558  
                     // do not have time to implement code to display them (we wanted
 559  
                     // to implement a lightbox for this).  
 560  0
                     KSNotifier.add(new KSNotification("Unable to save, please check fields for errors or missing information on this and other tabs", false, true, 5000));
 561  
                     
 562  0
                     okCallback.exec(false);
 563  0
                 } else {
 564  0
                         refreshModelAndView(result);
 565  0
                     resetFieldInteractionFlag();
 566  0
                     configurer.applyPermissions();
 567  0
                     handleSpecializations();
 568  0
                     throwAfterSaveEvent();
 569  0
                     HistoryManager.logHistoryChange();
 570  0
                     ViewContext viewContext = getViewContext();
 571  0
                     viewContext.setId(getStringProperty(ProgramConstants.ID));
 572  0
                     viewContext.setIdType(IdType.OBJECT_ID);
 573  
 
 574  0
                                     if (ValidatorClientUtils.hasWarnings(validationResults)){
 575  
                                             //Show validation warnings for major
 576  0
                                             isValid(result.getValidationResults(), false, true);                                            
 577  0
                                             KSNotifier.show("Saved with Warnings");
 578  
                                     } else {
 579  0
                         KSNotifier.show(ProgramProperties.get().common_successfulSave());
 580  
                                     }                                  
 581  
                     
 582  
                     // add to recently viewed now that we're sure to know the program's id
 583  0
                     ViewContext docContext = new ViewContext();
 584  0
                     docContext.setId(getStringProperty(ProgramConstants.ID));
 585  0
                     docContext.setIdType(IdType.OBJECT_ID);
 586  0
                     docContext.setAttribute(ProgramConstants.TYPE, ProgramConstants.MAJOR_LU_TYPE_ID + '/' + ProgramSections.PROGRAM_DETAILS_VIEW);
 587  0
                     RecentlyViewedHelper.addDocument(getProgramName(),
 588  
                     HistoryManager.appendContext(AppLocations.Locations.VIEW_PROGRAM.getLocation(), docContext));
 589  0
                         okCallback.exec(true);
 590  0
                         processCurrentView();                                                
 591  
                 }
 592  0
             }
 593  
         });
 594  0
     }
 595  
 
 596  
     private void processCurrentView() {
 597  0
         Enum<?> currentView = getCurrentViewEnum();
 598  0
         if (currentView.name().equals(ProgramSections.VIEW_ALL.name())) {
 599  0
             HistoryManager.navigate(AppLocations.Locations.VIEW_PROGRAM.getLocation(), getViewContext());
 600  
         } else {
 601  0
             showView(currentView);
 602  
         }
 603  0
     }
 604  
 
 605  
     /**
 606  
      * Handles after save work for specializations.
 607  
      */
 608  
     private void handleSpecializations() {
 609  0
         String newVariationId = null;
 610  0
         Data variations = programModel.get(ProgramConstants.VARIATIONS);
 611  0
         for (Data.Property prop : variations) {
 612  0
             String varId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
 613  0
             if (!existingVariationIds.contains(varId)) {
 614  0
                 newVariationId = varId;
 615  0
                 existingVariationIds.add(newVariationId);
 616  0
                 break;
 617  
             }
 618  0
         }
 619  0
         if (newVariationId != null) {
 620  0
             eventBus.fireEvent(new SpecializationCreatedEvent(newVariationId));
 621  
         } else {
 622  0
             eventBus.fireEvent(new SpecializationUpdateEvent(variations));
 623  
         }
 624  0
     }
 625  
 
 626  
     private void throwAfterSaveEvent() {
 627  0
         eventBus.fireEvent(new AfterSaveEvent(programModel, this));
 628  0
     }
 629  
 
 630  
     @Override
 631  
     public void onModelLoadedEvent() {
 632  0
         Enum<?> changeSection = ProgramRegistry.getSection();
 633  0
         if (changeSection != null) {
 634  0
             showView(changeSection);
 635  0
             ProgramRegistry.setSection(null);
 636  
         } else {
 637  0
             String id = getStringProperty(ProgramConstants.ID);
 638  0
             if (id == null) {
 639  0
                 showView(ProgramSections.PROGRAM_DETAILS_EDIT);
 640  
             } else {
 641  0
                 showView(ProgramSections.SUMMARY);
 642  
             }
 643  
         }
 644  
 
 645  0
     }
 646  
 
 647  
         @Override
 648  
         public void beforeShow(final Callback<Boolean> onReadyCallback) {
 649  0
                 if(!initialized){
 650  0
                         Application.getApplicationContext().clearCrossConstraintMap(null);
 651  0
                         Application.getApplicationContext().clearPathToFieldMapping(null);
 652  
                 }
 653  
                 //Clear the parent path again
 654  0
                 Application.getApplicationContext().setParentPath("");
 655  0
                 super.beforeShow(onReadyCallback);
 656  0
         }
 657  
 
 658  
         //Before show is called before the model is bound to the widgets. We need to update cross constraints after widget binding
 659  
         //This gets called twice which is not optimal
 660  
         @Override
 661  
         public <V extends Enum<?>> void showView(V viewType,
 662  
                         final Callback<Boolean> onReadyCallback) {
 663  0
                 Callback<Boolean> updateCrossConstraintsCallback = new Callback<Boolean>(){
 664  
                         public void exec(Boolean result) {
 665  0
                                 onReadyCallback.exec(result);
 666  0
                         for(HasCrossConstraints crossConstraint:Application.getApplicationContext().getCrossConstraints(null)){
 667  0
                                 crossConstraint.reprocessWithUpdatedConstraints();
 668  
                         }
 669  0
                         showWarnings();        
 670  0
                         }
 671  
         };
 672  0
                 super.showView(viewType, updateCrossConstraintsCallback);
 673  0
         }
 674  
 
 675  
         //Ensure that the managing bodies section view is updated before the user edits specializations
 676  
         @Override
 677  
         public void beforeViewChange(final Enum<?> viewChangingTo, final Callback<Boolean> okToChangeCallback){
 678  0
             final Callback<Boolean> reallyOkToChange = new Callback<Boolean>() {
 679  
 
 680  
             @Override
 681  
             public void exec(Boolean result) {
 682  0
                 if (result) {
 683  0
                     if (LUMViews.VARIATION_EDIT.equals(viewChangingTo)) {
 684  0
                         getView(ProgramSections.MANAGE_BODIES_EDIT, new Callback<View>() {
 685  
                             @Override
 686  
                             public void exec(final View view) {
 687  0
                                 if (view != null && view instanceof SectionView) {
 688  0
                                     requestModel(new ModelRequestCallback<DataModel>() {
 689  
                                         public void onModelReady(DataModel model) {
 690  0
                                             ((SectionView) view).updateWidgetData(model);
 691  0
                                             okToChangeCallback.exec(true);
 692  0
                                         }
 693  
 
 694  
                                         public void onRequestFail(Throwable cause) {
 695  0
                                             okToChangeCallback.exec(false);
 696  0
                                         }
 697  
                                     });
 698  
                                 } else {
 699  0
                                     okToChangeCallback.exec(true);
 700  
                                 }
 701  0
                             }
 702  
                         });
 703  
                     } else {
 704  0
                         okToChangeCallback.exec(true);
 705  
                     }
 706  
                 }
 707  0
             }
 708  
             };
 709  0
             super.beforeViewChange(viewChangingTo, reallyOkToChange);
 710  0
                 this.showExport(isExportButtonActive());        // KSLAB-1916
 711  0
         }
 712  
                 
 713  
     public ProgramRequirementsDataModel getReqDataModel() {
 714  0
         return reqDataModel;
 715  
     }
 716  
 
 717  
     public ProgramRequirementsDataModel getReqDataModelComp() {
 718  0
         return reqDataModelComp;
 719  
     }
 720  
 }