View Javadoc

1   package org.kuali.student.lum.program.client.variation.edit;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.kuali.student.common.assembly.data.Data;
7   import org.kuali.student.common.ui.client.application.Application;
8   import org.kuali.student.common.ui.client.application.ViewContext;
9   import org.kuali.student.common.ui.client.mvc.Callback;
10  import org.kuali.student.common.ui.client.mvc.DataModel;
11  import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
12  import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
13  import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
14  import org.kuali.student.common.ui.client.widgets.KSButton;
15  import org.kuali.student.common.ui.client.widgets.KSButtonAbstract;
16  import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
17  import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
18  import org.kuali.student.common.validation.dto.ValidationResultInfo;
19  import org.kuali.student.lum.common.client.widgets.AppLocations;
20  import org.kuali.student.lum.program.client.ProgramConstants;
21  import org.kuali.student.lum.program.client.ProgramRegistry;
22  import org.kuali.student.lum.program.client.ProgramSections;
23  import org.kuali.student.lum.program.client.events.ChangeViewEvent;
24  import org.kuali.student.lum.program.client.events.ModelLoadedEvent;
25  import org.kuali.student.lum.program.client.events.SpecializationCreatedEvent;
26  import org.kuali.student.lum.program.client.events.SpecializationSaveEvent;
27  import org.kuali.student.lum.program.client.events.SpecializationUpdateEvent;
28  import org.kuali.student.lum.program.client.events.StoreSpecRequirementIDsEvent;
29  import org.kuali.student.lum.program.client.major.MajorController;
30  import org.kuali.student.lum.program.client.major.edit.MajorEditController;
31  import org.kuali.student.lum.program.client.major.proposal.MajorProposalController;
32  import org.kuali.student.lum.program.client.properties.ProgramProperties;
33  import org.kuali.student.lum.program.client.variation.VariationController;
34  import org.kuali.student.lum.program.client.widgets.ProgramSideBar;
35  
36  import com.google.gwt.core.client.GWT;
37  import com.google.gwt.event.dom.client.ClickEvent;
38  import com.google.gwt.event.dom.client.ClickHandler;
39  import com.google.gwt.event.shared.HandlerManager;
40  import com.google.gwt.user.client.Window;
41  
42  /**
43   * @author Igor
44   */
45  public class VariationEditController extends VariationController {
46  
47      private final KSButton saveButton = new KSButton(ProgramProperties.get().common_save());
48      private final KSButton cancelButton = new KSButton(ProgramProperties.get().common_cancel(), KSButtonAbstract.ButtonStyle.ANCHOR_LARGE_CENTERED);
49  
50      private String currentId;
51  
52      public VariationEditController(DataModel programModel, ViewContext viewContext, HandlerManager eventBus, MajorController majorController) {
53          super(programModel, viewContext, eventBus, majorController);
54          configurer = GWT.create(VariationEditConfigurer.class);
55          sideBar.setState(ProgramSideBar.State.EDIT);
56          if (getStringProperty(ProgramConstants.ID) != null) {
57              setDefaultView(ProgramSections.SUMMARY);
58          }
59          initHandlers();
60      }
61  
62      private void initHandlers() {
63          saveButton.addClickHandler(new ClickHandler() {
64  
65              @Override
66              public void onClick(ClickEvent event) {
67                  doSave();
68              }
69          });
70          cancelButton.addClickHandler(new ClickHandler() {
71  
72              @Override
73              public void onClick(ClickEvent event) {
74                  doCancel();
75              }
76          });
77          ModelLoadedEvent.Handler modelLoadedHandler = new ModelLoadedEvent.Handler() {
78              @Override
79              public void onEvent(ModelLoadedEvent event) {
80                  DataModel dataModel = event.getModel();
81                  Data variationMap = dataModel.get(ProgramConstants.VARIATIONS);
82                  if (variationMap != null) {
83                      int row = 0;
84                      for (Data.Property property : variationMap) {
85                          final Data variationData = property.getValue();
86                          if (variationData.get(ProgramConstants.ID).equals(currentId)) {
87                              programModel.setRoot(variationData);
88                              ProgramRegistry.setData(variationData);
89                              ProgramRegistry.setRow(row);
90                              setContentTitle(getProgramName());
91                              row++;
92                              return;
93                          }
94                      }
95                  }
96              }
97          };
98          ProgramRegistry.addHandler(ModelLoadedEvent.TYPE, modelLoadedHandler);
99          eventBus.addHandler(ModelLoadedEvent.TYPE, modelLoadedHandler);
100 
101         ChangeViewEvent.Handler changeViewHandler = new ChangeViewEvent.Handler() {
102             @Override
103             public void onEvent(ChangeViewEvent event) {
104                 Enum<?> viewToken = event.getViewToken();
105                 if (!viewToken.name().equals(ProgramSections.SPECIALIZATIONS_EDIT.name())) {
106                     showView(viewToken);
107                 }
108             }
109         };
110         ProgramRegistry.addHandler(ChangeViewEvent.TYPE, changeViewHandler);
111         eventBus.addHandler(ChangeViewEvent.TYPE, changeViewHandler);
112         eventBus.addHandler(SpecializationCreatedEvent.TYPE, new SpecializationCreatedEvent.Handler() {
113 
114             @Override
115             public void onEvent(SpecializationCreatedEvent event) {
116                 programModel.getRoot().set(ProgramConstants.ID, event.getSpecializationId());
117                 showWarnings();
118             }
119         });
120 
121         eventBus.addHandler(SpecializationUpdateEvent.TYPE, new SpecializationUpdateEvent.Handler() {
122             @Override
123             public void onEvent(SpecializationUpdateEvent event) {
124                 // update our model to the updated specialization
125 
126                 // gotta find it first
127                 String currSpecializationId = programModel.getRoot().get(ProgramConstants.ID);
128                 for (Data.Property prop : event.getSpecializations()) {
129                     String specId = (String) ((Data) prop.getValue()).get(ProgramConstants.ID);
130 
131                     if (null != specId && specId.equals(currSpecializationId) && prop.getValueType().equals(Data.class)) {
132                         // found it
133                         programModel.setRoot((Data) prop.getValue());
134                         showView(getCurrentViewEnum());
135                     }
136                 }
137                 
138                 //update with any new warnings that exist on specialization
139                 showWarnings();
140             }
141         });
142 
143         StoreSpecRequirementIDsEvent.Handler requirementsHandler = new StoreSpecRequirementIDsEvent.Handler() {
144             @Override
145             public void onEvent(StoreSpecRequirementIDsEvent event) {
146                 final String programId = event.getProgramId();
147                 final List<String> ids = event.getProgramRequirementIds();
148 
149                 requestModel(new ModelRequestCallback<DataModel>() {
150                     @Override
151                     public void onModelReady(final DataModel model) {
152                         Data programRequirements = null;
153 
154                         // find the specialization that we need to update
155                         //for (Data.Property property : model.getRoot()) {
156                         Data variationData = model.getRoot();
157                         if (variationData.get(ProgramConstants.ID).equals(programId)) {
158                             variationData.set(ProgramConstants.PROGRAM_REQUIREMENTS, new Data());
159                             programRequirements = variationData.get(ProgramConstants.PROGRAM_REQUIREMENTS);
160                             // break;
161                         }
162                         // }
163 
164                         if (programRequirements == null) {
165                             Window.alert("Cannot find program requirements in data model.");
166                             GWT.log("Cannot find program requirements in data model", null);
167                             return;
168                         }
169 
170                         for (String id : ids) {
171                             programRequirements.add(id);
172                         }
173                         doSave();
174                     }
175 
176                     @Override
177                     public void onRequestFail(Throwable cause) {
178                         GWT.log("Unable to retrieve model for validation and save", cause);
179                     }
180 
181                 });
182             }
183         };
184         ProgramRegistry.addHandler(StoreSpecRequirementIDsEvent.TYPE, requirementsHandler);
185         eventBus.addHandler(StoreSpecRequirementIDsEvent.TYPE, requirementsHandler);
186     }
187 
188     @Override
189     protected void fireUpdateEvent(Callback<Boolean> okToChange) {
190         doSave(okToChange);
191     }
192 
193     private void doSave(final Callback<Boolean> okToChange) {
194         requestModel(new ModelRequestCallback<DataModel>() {
195             @Override
196             public void onModelReady(final DataModel model) {
197                 VariationEditController.this.updateModelFromCurrentView();
198                 model.setParentPath(ProgramConstants.VARIATIONS + "/" + ProgramRegistry.getRow());
199                 model.validate(new Callback<List<ValidationResultInfo>>() {
200                     @Override
201                     public void exec(List<ValidationResultInfo> results) {
202                         boolean isSectionValid = isValid(results, true);
203                         if (isSectionValid) {
204                             saveData(model);
205                             okToChange.exec(true);
206                         } else {
207                             okToChange.exec(false);
208                             KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
209                         }
210                     }
211                 });
212             }
213 
214             @Override
215             public void onRequestFail(Throwable cause) {
216                 GWT.log("Unable to retrieve model for validation and save", cause);
217             }
218 
219         });
220     }
221 
222     @Override
223     protected void configureView() {
224         super.configureView();
225         if (!initialized) {
226             List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
227             excludedViews.add(ProgramSections.PROGRAM_REQUIREMENTS_EDIT);
228             excludedViews.add(ProgramSections.SUPPORTING_DOCUMENTS_EDIT);
229             excludedViews.add(ProgramSections.SUMMARY);
230             addCommonButton(ProgramProperties.get().program_menu_sections(), saveButton, excludedViews);
231             addCommonButton(ProgramProperties.get().program_menu_sections(), cancelButton, excludedViews);
232             initialized = true;
233         }
234 
235     }
236 
237     @Override
238     protected void resetModel() {
239         currentId = getStringProperty(ProgramConstants.ID);
240         programModel.resetRoot();
241     }
242 
243     private void doCancel() {
244        navigateToParent(ProgramSections.SUMMARY);
245     }
246 
247     @Override
248     protected void doSave() {
249         doSave(NO_OP_CALLBACK);
250     }
251 
252     private void saveData(DataModel model) {
253         currentId = model.get(ProgramConstants.ID);
254         eventBus.fireEvent(new SpecializationSaveEvent(model.getRoot()));
255         setContentTitle(getProgramName());
256         setName(getProgramName());
257         resetFieldInteractionFlag();
258     }
259 
260     @Override
261     protected void navigateToParent() {
262         navigateToParent(ProgramSections.SPECIALIZATIONS_EDIT);
263     }
264 
265     private void navigateToParent(ProgramSections parentSection) {
266     	String appLoc = "";
267     	
268     	if(!(majorController instanceof MajorProposalController))
269     		appLoc = AppLocations.Locations.EDIT_PROGRAM_SPEC.getLocation();
270     	else
271     		appLoc = AppLocations.Locations.PROGRAM_PROPOSAL.getLocation();
272         String path = HistoryManager.appendContext(appLoc, getViewContext()) + "/" + parentSection;
273         HistoryManager.navigate(path);
274     }
275 
276     
277 	@Override
278 	public void beforeShow(final Callback<Boolean> onReadyCallback) {
279     	//clear all cross constraints that start with variations
280     	Application.getApplicationContext().clearCrossConstraintsWithStartingPath(null,ProgramConstants.VARIATIONS);
281     	
282     	//Set the context parent path so the proper mapping is retained 
283     	String newParentPath = ProgramConstants.VARIATIONS+"/"+org.kuali.student.lum.program.client.ProgramRegistry.getRow()+"/";
284     	Application.getApplicationContext().setParentPath(newParentPath);
285 		
286     	//This callback restricts values displayed in widget (eg. dropdowns, pickers) based on a cross field selection
287     	//and updates the warning messages displayed for the variation. A callback is used since we need the parent 
288     	//ProgramController to finish configuring the view before proceeding.
289 		Callback<Boolean> finalizeVariationView = new Callback<Boolean>(){
290 			public void exec(Boolean result) {
291 		        //Update widgets with constraints
292 				for(HasCrossConstraints crossConstraint:Application.getApplicationContext().getCrossConstraints(null)){
293 		        	crossConstraint.reprocessWithUpdatedConstraints();
294 		        }
295 
296 		        onReadyCallback.exec(result);
297 			}
298         };
299 		super.beforeShow(finalizeVariationView);
300 	}
301 
302 	//Before show is called before the model is bound to the widgets. We need to update cross constraints after widget binding
303 	//This gets called twice which is not optimal
304 	@Override
305 	public <V extends Enum<?>> void showView(V viewType,
306 			final Callback<Boolean> onReadyCallback) {
307 		Callback<Boolean> updateCrossConstraintsCallback = new Callback<Boolean>(){
308 			public void exec(Boolean result) {
309 				onReadyCallback.exec(result);
310 		        showWarnings();	
311 			}
312         };
313 		super.showView(viewType, updateCrossConstraintsCallback);
314 	}
315 	
316 }