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