Clover Coverage Report - KS LUM 1.2-M4-SNAPSHOT (Aggregated)
Coverage timestamp: Wed Jul 20 2011 13:25:47 EDT
../../../../../../img/srcFileCovDistChart0.png 43% of files have more coverage
189   540   82   4.61
60   400   0.43   41
41     2  
1    
 
  ProgramController       Line # 56 189 0% 82 290 0% 0.0
 
No Tests
 
1    package org.kuali.student.lum.program.client;
2   
3    import java.util.ArrayList;
4    import java.util.HashMap;
5    import java.util.List;
6    import java.util.Map;
7   
8    import org.kuali.student.common.assembly.data.Data;
9    import org.kuali.student.common.assembly.data.Metadata;
10    import org.kuali.student.common.dto.DtoConstants;
11    import org.kuali.student.common.rice.authorization.PermissionType;
12    import org.kuali.student.common.ui.client.application.ViewContext;
13    import org.kuali.student.common.ui.client.configurable.mvc.layouts.MenuSectionController;
14    import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
15    import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
16    import org.kuali.student.common.ui.client.mvc.Callback;
17    import org.kuali.student.common.ui.client.mvc.DataModel;
18    import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
19    import org.kuali.student.common.ui.client.mvc.ModelProvider;
20    import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
21    import org.kuali.student.common.ui.client.mvc.View;
22    import org.kuali.student.common.ui.client.mvc.dto.ReferenceModel;
23    import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
24    import org.kuali.student.common.ui.client.service.DataSaveResult;
25    import org.kuali.student.common.ui.client.util.ExportElement;
26    import org.kuali.student.common.ui.client.util.ExportUtils;
27    import org.kuali.student.common.ui.client.widgets.KSButton;
28    import org.kuali.student.common.ui.client.widgets.KSButtonAbstract;
29    import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
30    import org.kuali.student.common.ui.client.widgets.dialog.ButtonMessageDialog;
31    import org.kuali.student.common.ui.client.widgets.field.layout.button.ButtonGroup;
32    import org.kuali.student.common.ui.client.widgets.field.layout.button.YesNoCancelGroup;
33    import org.kuali.student.common.ui.shared.IdAttributes;
34    import org.kuali.student.common.ui.shared.IdAttributes.IdType;
35    import org.kuali.student.core.comments.ui.client.widgets.commenttool.CommentTool;
36    import org.kuali.student.lum.common.client.helpers.RecentlyViewedHelper;
37    import org.kuali.student.lum.common.client.widgets.AppLocations;
38    import org.kuali.student.lum.program.client.events.ModelLoadedEvent;
39    import org.kuali.student.lum.program.client.events.UpdateEvent;
40    import org.kuali.student.lum.program.client.properties.ProgramProperties;
41    import org.kuali.student.lum.program.client.rpc.AbstractCallback;
42    import org.kuali.student.lum.program.client.rpc.MajorDisciplineRpcService;
43    import org.kuali.student.lum.program.client.rpc.MajorDisciplineRpcServiceAsync;
44    import org.kuali.student.lum.program.client.widgets.ProgramSideBar;
45   
46    import com.google.gwt.core.client.GWT;
47    import com.google.gwt.event.dom.client.ClickEvent;
48    import com.google.gwt.event.dom.client.ClickHandler;
49    import com.google.gwt.event.shared.HandlerManager;
50    import com.google.gwt.user.client.ui.Label;
51    import com.google.gwt.user.client.ui.Widget;
52   
53    /**
54    * @author Igor
55    */
 
56    public abstract class ProgramController extends MenuSectionController {
57   
58    protected MajorDisciplineRpcServiceAsync programRemoteService;
59   
60    protected boolean initialized = false;
61   
62    protected DataModel programModel;
63   
64    protected AbstractProgramConfigurer configurer;
65   
66    protected HandlerManager eventBus;
67   
68    protected Label statusLabel = new Label();
69   
70    protected ProgramSideBar sideBar;
71   
72    private boolean needToLoadOldModel = false;
73   
74    private ProgramStatus lastLoadedStatus;
75   
76    protected boolean reloadMetadata = false;
77   
78    protected boolean processBeforeShow = true;
79   
80    /**
81    * Constructor.
82    *
83    * @param programModel
84    */
 
85  0 toggle public ProgramController(String name, DataModel programModel, ViewContext viewContext, HandlerManager eventBus) {
86  0 super();
87  0 programRemoteService = createProgramRemoteService();
88  0 this.eventBus = eventBus;
89  0 this.programModel = programModel;
90  0 setViewContext(viewContext);
91  0 initializeModel();
92    }
93   
94   
95    /**
96    * Create a ProgramRpcServiceAsync appropriate for this Controller
97    */
 
98  0 toggle protected MajorDisciplineRpcServiceAsync createProgramRemoteService() {
99  0 return GWT.create(MajorDisciplineRpcService.class);
100    }
101   
 
102  0 toggle @Override
103    public void beforeViewChange(Enum<?> viewChangingTo, final Callback<Boolean> okToChange) {
104  0 if (processBeforeShow) {
105  0 super.beforeViewChange(viewChangingTo, new Callback<Boolean>() {
106   
 
107  0 toggle @Override
108    public void exec(Boolean result) {
109  0 if (result) {
110  0 if (getCurrentView() instanceof SectionView && ((SectionView) getCurrentView()).isDirty()) {
111  0 ButtonGroup<ButtonEnumerations.YesNoCancelEnum> buttonGroup = new YesNoCancelGroup();
112  0 final ButtonMessageDialog<ButtonEnumerations.YesNoCancelEnum> dialog = new ButtonMessageDialog<ButtonEnumerations.YesNoCancelEnum>("Warning", "You may have unsaved changes. Save changes?", buttonGroup);
113  0 buttonGroup.addCallback(new Callback<ButtonEnumerations.YesNoCancelEnum>() {
114   
 
115  0 toggle @Override
116    public void exec(ButtonEnumerations.YesNoCancelEnum result) {
117  0 switch (result) {
118  0 case YES:
119  0 dialog.hide();
120  0 fireUpdateEvent(okToChange);
121  0 break;
122  0 case NO:
123  0 dialog.hide();
124  0 resetModel();
125  0 needToLoadOldModel = true;
126  0 resetFieldInteractionFlag();
127  0 okToChange.exec(true);
128  0 break;
129  0 case CANCEL:
130  0 okToChange.exec(false);
131  0 dialog.hide();
132    // Because this event fires after the history change event we need to "undo" the history events.
133  0 HistoryManager.logHistoryChange();
134  0 break;
135    }
136    }
137    });
138  0 dialog.show();
139    } else {
140  0 okToChange.exec(true);
141    }
142    } else {
143  0 okToChange.exec(false);
144    }
145    }
146    });
147    } else {
148  0 processBeforeShow = true;
149    }
150    }
151   
 
152  0 toggle protected void fireUpdateEvent(final Callback<Boolean> okToChange) {
153  0 eventBus.fireEvent(new UpdateEvent(okToChange));
154    }
155   
 
156  0 toggle protected void resetModel() {
157  0 programModel.resetRoot();
158    }
159   
 
160  0 toggle protected void resetFieldInteractionFlag() {
161  0 View currentView = getCurrentView();
162  0 if (currentView instanceof Section) {
163  0 ((Section) currentView).resetFieldInteractionFlags();
164    }
165    }
166   
167    /**
168    * Initialized model of the controller.
169    */
 
170  0 toggle private void initializeModel() {
171  0 setDefaultModelId(ProgramConstants.PROGRAM_MODEL_ID);
172  0 registerModel(ProgramConstants.PROGRAM_MODEL_ID, new ModelProvider<DataModel>() {
 
173  0 toggle @Override
174    public void requestModel(final ModelRequestCallback<DataModel> callback) {
175  0 if (programModel.getRoot() == null || programModel.getRoot().size() == 0) {
176  0 loadModel(callback);
177    } else {
178  0 callback.onModelReady(programModel);
179    }
180    }
181    });
182    }
183   
184   
 
185  0 toggle @Override
186    public void requestModel(Class modelType, ModelRequestCallback callback) {
187  0 if (modelType == ReferenceModel.class) {
188  0 ReferenceModel referenceModel = new ReferenceModel();
189  0 referenceModel.setReferenceId(ProgramUtils.getProgramId(programModel));
190  0 referenceModel.setReferenceTypeKey(ProgramConstants.MAJOR_REFERENCE_TYPE_ID);
191  0 referenceModel.setReferenceType(ProgramConstants.MAJOR_LU_TYPE_ID);
192  0 Map<String, String> attributes = new HashMap<String, String>();
193  0 attributes.put("name", getStringProperty("name"));
194  0 referenceModel.setReferenceAttributes(attributes);
195  0 callback.onModelReady(referenceModel);
196    } else {
197  0 super.requestModel(modelType, callback);
198    }
199    }
200   
201   
202    /**
203    * Loads data model from the server.
204    *
205    * @param callback we have to invoke this callback when model is loaded or failed.
206    */
 
207  0 toggle protected void loadModel(final ModelRequestCallback<DataModel> callback) {
208  0 programRemoteService.getData(getViewContext().getId(), new AbstractCallback<Data>(ProgramProperties.get().common_retrievingData()) {
209   
 
210  0 toggle @Override
211    public void onFailure(Throwable caught) {
212  0 super.onFailure(caught);
213  0 callback.onRequestFail(caught);
214    }
215   
 
216  0 toggle @Override
217    public void onSuccess(Data result) {
218  0 super.onSuccess(result);
219  0 programModel.setRoot(result);
220  0 setHeaderTitle();
221  0 callback.onModelReady(programModel);
222    }
223    });
224    }
225   
 
226  0 toggle private void setModelData() {
227  0 setHeaderTitle();
228  0 setStatus();
229  0 configurer.applyPermissions();
230    //We don't want to throw ModelLoadedEvent when we just want to rollback the model
231  0 if (needToLoadOldModel) {
232  0 needToLoadOldModel = false;
233    } else {
234  0 String id = ProgramUtils.getProgramId(programModel);
235  0 if (null != id) {
236    // add to recently viewed
237  0 ViewContext docContext = new ViewContext();
238  0 docContext.setId(id);
239  0 docContext.setIdType(IdType.OBJECT_ID);
240  0 String pgmType = getStringProperty(ProgramConstants.TYPE);
241  0 docContext.setAttribute(ProgramConstants.TYPE, pgmType + '/' + ProgramSections.PROGRAM_DETAILS_VIEW);
242  0 RecentlyViewedHelper.addDocument(getProgramName(),
243    HistoryManager.appendContext(getProgramViewLocation(pgmType), docContext));
244    }
245  0 eventBus.fireEvent(new ModelLoadedEvent(programModel));
246  0 onModelLoadedEvent();
247    }
248    }
249   
 
250  0 toggle private String getProgramViewLocation(String pgmType) {
251  0 if (ProgramClientConstants.MAJOR_PROGRAM.equals(pgmType)) {
252  0 return AppLocations.Locations.VIEW_PROGRAM.getLocation();
253  0 } else if (ProgramClientConstants.CORE_PROGRAM.equals(pgmType)) {
254  0 return AppLocations.Locations.VIEW_CORE_PROGRAM.getLocation();
255  0 } else if (ProgramClientConstants.CREDENTIAL_PROGRAM_TYPES.contains(pgmType)) {
256  0 return AppLocations.Locations.VIEW_BACC_PROGRAM.getLocation();
257    }
258  0 return null;
259    }
260   
 
261  0 toggle protected void setStatus() {
262  0 statusLabel.setText(ProgramProperties.get().common_status(getStringProperty(ProgramConstants.STATE)));
263    }
264   
 
265  0 toggle public String getProgramName() {
266  0 String name = getStringProperty(ProgramConstants.LONG_TITLE);
267  0 if (name == null) {
268  0 name = ProgramProperties.get().common_newProgram();
269    }
270  0 return name;
271    }
272   
273    /**
274    * Got invoked by framework before showing the view of the controller.
275    *
276    * @param onReadyCallback
277    */
 
278  0 toggle @Override
279    public void beforeShow(final Callback<Boolean> onReadyCallback) {
280  0 if (programModel.getRoot() == null) {
281  0 loadModel(new ModelRequestCallback<DataModel>() {
 
282  0 toggle @Override
283    public void onModelReady(DataModel model) {
284  0 if (loadMetadataCondition()) {
285  0 loadMetadata(onReadyCallback);
286    } else {
287   
288  0 onReadyCallback.exec(true);
289    }
290    }
291   
 
292  0 toggle @Override
293    public void onRequestFail(Throwable cause) {
294  0 GWT.log(cause.getMessage());
295    }
296    });
297    } else {
298  0 afterMetadataLoaded(onReadyCallback);
299    }
300    }
301   
302    /**
303    * We should only load metadata if the status of model is changed.
304    *
305    * @return
306    */
 
307  0 toggle protected boolean loadMetadataCondition() {
308  0 return lastLoadedStatus == null || ProgramStatus.of(programModel) != lastLoadedStatus;
309    }
310   
311    /**
312    * Loads metadata from the server.
313    *
314    * @param onReadyCallback
315    */
 
316  0 toggle protected void loadMetadata(final Callback<Boolean> onReadyCallback) {
317  0 Map<String, String> idAttributes = new HashMap<String, String>();
318  0 ViewContext viewContext = getViewContext();
319  0 IdType idType = viewContext.getIdType();
320  0 String viewContextId = null;
321  0 if (idType != null) {
322  0 idAttributes.put(IdAttributes.ID_TYPE, idType.toString());
323  0 viewContextId = viewContext.getId();
324  0 if (idType == IdType.COPY_OF_OBJECT_ID) {
325  0 viewContextId = null;
326    }
327    }
328  0 if (programModel.getRoot() != null) {
329  0 ProgramStatus programStatus = ProgramStatus.of(programModel);
330  0 idAttributes.put(DtoConstants.DTO_STATE, programStatus.getValue());
331  0 if (programStatus.getNextStatus() != null) {
332  0 idAttributes.put(DtoConstants.DTO_NEXT_STATE, programStatus.getNextStatus().getValue());
333    }
334    }
335  0 programRemoteService.getMetadata(viewContextId, idAttributes, new AbstractCallback<Metadata>() {
336   
 
337  0 toggle @Override
338    public void onSuccess(Metadata result) {
339  0 super.onSuccess(result);
340  0 DataModelDefinition def = new DataModelDefinition(result);
341  0 programModel.setDefinition(def);
342  0 lastLoadedStatus = ProgramStatus.of(programModel);
343  0 afterMetadataLoaded(onReadyCallback);
344    }
345   
 
346  0 toggle @Override
347    public void onFailure(Throwable caught) {
348  0 super.onFailure(caught);
349  0 onReadyCallback.exec(false);
350    }
351    });
352    }
353   
 
354  0 toggle protected void configureView() {
355  0 addStyleName("programController");
356  0 configurer.setModelDefinition(programModel.getDefinition());
357  0 configurer.configure(this);
358  0 addContentWidget(statusLabel);
359  0 setSideBarWidget(sideBar);
360    }
361   
 
362  0 toggle @Override
363    public void setViewContext(ViewContext viewContext) {
364  0 super.setViewContext(viewContext);
365  0 if (viewContext.getId() != null && !viewContext.getId().isEmpty()) {
366  0 viewContext.setPermissionType(PermissionType.OPEN);
367    } else {
368  0 viewContext.setPermissionType(PermissionType.INITIATE);
369    }
370    }
371   
372    /**
373    * Called when metadata is loaded.
374    *
375    * @param onReadyCallback
376    */
 
377  0 toggle protected void afterMetadataLoaded(Callback<Boolean> onReadyCallback) {
378  0 if (!reloadMetadata) {
379  0 configureView();
380  0 onReadyCallback.exec(true);
381  0 reloadMetadata = true;
382    } else {
383  0 onReadyCallback.exec(true);
384  0 ProgramUtils.syncMetadata(configurer, programModel.getDefinition());
385    }
386  0 if (programModel.getRoot() != null) {
387  0 setModelData();
388    }
389    }
390   
 
391  0 toggle protected void setHeaderTitle() {
392  0 String title = getProgramName();
393  0 this.setContentTitle(title);
394  0 this.setName(title);
395    }
396   
 
397  0 toggle protected Widget createCommentPanel() {
398  0 final CommentTool commentTool = new CommentTool(ProgramSections.COMMENTS, "Comments", "kuali.comment.type.generalRemarks", "Program Comments");
399  0 commentTool.setController(this);
400  0 KSButton commentsButton = new KSButton(ProgramProperties.get().comments_button(), KSButtonAbstract.ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
401   
 
402  0 toggle @Override
403    public void onClick(ClickEvent event) {
404  0 commentTool.show();
405    }
406    });
407  0 return commentsButton;
408    }
409   
 
410  0 toggle protected void doSave() {
411    }
412   
413   
414    /**
415    * Update the state of the program and all of its statements.
416    * <p>
417    * This is only called when the state change event fires.
418    * <p>
419    * There are several types of programs (majorDiscipline, core, credential). The
420    * state of each program changes when buttons are pressed. For example, pressing
421    * the activate button may change the state of the program from draft to active.
422    * <p>
423    * This method is triggered when the state changes. It will pass the
424    * new state to the controller servlet, which will then use it to update the state
425    * by calling the web services.
426    * <p>
427    * Note that state and status are different.
428    * <p>
429    * It is placed in ProgramController so core, credential, etc all have access it.
430    * <p>
431    *
432    *
433    * @param programModel a map containing data representing the program
434    * @param state the state we changed to
435    * @param callback will return true if update succeeded
436    */
 
437  0 toggle protected void updateState(String state, final Callback<Boolean> okCallback) {
438   
439  0 programRemoteService.updateState(programModel.getRoot(), state, new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_savingData()) {
 
440  0 toggle @Override
441    public void onSuccess(DataSaveResult result) {
442  0 if(result.getValidationResults()==null || result.getValidationResults().isEmpty()){
443  0 super.onSuccess(result);
444  0 okCallback.exec(true);
445  0 refreshModelAndView(result);
446    }else{
447    //Remove the blocking progress
448  0 super.onSuccess(result);
449    //Do proper validation error handling
450  0 isValid(result.getValidationResults(), false, true);
451  0 ProgramUtils.handleValidationErrorsForSpecializations(result.getValidationResults(), programModel);
452    //return false since this was not successful
453  0 okCallback.exec(false);
454    }
455    }
456   
457    });
458   
459    }
460    /**
461    * This method will refresh the model and view with the data sent back from
462    * the server.
463    *
464    */
 
465  0 toggle public void refreshModelAndView(DataSaveResult result){
466  0 if (result != null) {
467  0 programModel.setRoot(result.getValue());
468    }
469  0 setHeaderTitle();
470  0 setStatus();
471    }
472   
 
473  0 toggle public DataModel getProgramModel() {
474  0 return programModel;
475    }
476   
 
477  0 toggle public void onModelLoadedEvent() {
478    }
479   
 
480  0 toggle protected String getStringProperty(String key) {
481  0 return programModel.get(key);
482    }
483   
 
484  0 toggle protected Data getDataProperty(String key) {
485  0 return programModel.get(key);
486    }
487   
 
488  0 toggle public boolean isExportButtonActive() {
489  0 if (this.getCurrentViewEnum() != null) {
490  0 if (this.getCurrentViewEnum().equals(ProgramSections.SUMMARY)
491    || this.getCurrentViewEnum().equals(ProgramSections.VIEW_ALL)) {
492  0 return true;
493    } else {
494  0 return false;
495    }
496   
497    } else {
498  0 return false;
499    }
500    }
501   
 
502  0 toggle @Override
503    public ArrayList<ExportElement> getExportElementsFromView() {
504   
505  0 String viewName = null;
506  0 String sectionTitle = null;
507  0 View currentView = this.getCurrentView();
508  0 if (currentView != null) {
509   
510  0 ArrayList<ExportElement> exportElements = new ArrayList<ExportElement>();
511  0 if (currentView != null && currentView instanceof Section) {
512  0 Section currentSection = (Section) currentView;
513  0 List<Section> nestedSections = currentSection.getSections();
514  0 for (int i = 0; i < nestedSections.size(); i++) {
515  0 ExportElement sectionExportItem = new ExportElement();
516  0 ArrayList<ExportElement> subList = null;
517  0 Section nestedSection = nestedSections.get(i);
518  0 if (nestedSection != null && nestedSection instanceof SectionView) {
519  0 SectionView nestedSectionView = (SectionView) nestedSection;
520  0 viewName = nestedSectionView.getName();
521  0 sectionTitle = nestedSectionView.getTitle();
522  0 sectionExportItem.setSectionName(sectionTitle + " " + i + " - " + viewName);
523  0 sectionExportItem.setViewName(sectionTitle + " " + i + " - " + viewName);
524  0 subList = ExportUtils.getExportElementsFromView(nestedSectionView, subList, viewName, sectionTitle);
525  0 if (subList != null && subList.size()> 0) {
526  0 sectionExportItem.setSubset(subList);
527  0 exportElements.add(sectionExportItem);
528    }
529    }
530    }
531    }
532  0 return exportElements;
533   
534    } else {
535    // logger.warn("ExportUtils.getExportElementsFromView controller currentView is null :" + this.getClass().getName());
536    }
537  0 return null;
538   
539    }
540    }