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