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
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
82
83
84
85 public ProgramController(String name, DataModel programModel, ViewContext viewContext, HandlerManager eventBus) {
86 super();
87 programRemoteService = createProgramRemoteService();
88 this.eventBus = eventBus;
89 this.programModel = programModel;
90 setViewContext(viewContext);
91 initializeModel();
92 }
93
94
95
96
97
98 protected MajorDisciplineRpcServiceAsync createProgramRemoteService() {
99 return GWT.create(MajorDisciplineRpcService.class);
100 }
101
102 @Override
103 public void beforeViewChange(Enum<?> viewChangingTo, final Callback<Boolean> okToChange) {
104 if (processBeforeShow) {
105 super.beforeViewChange(viewChangingTo, new Callback<Boolean>() {
106
107 @Override
108 public void exec(Boolean result) {
109 if (result) {
110 if (getCurrentView() instanceof SectionView && ((SectionView) getCurrentView()).isDirty()) {
111 ButtonGroup<ButtonEnumerations.YesNoCancelEnum> buttonGroup = new YesNoCancelGroup();
112 final ButtonMessageDialog<ButtonEnumerations.YesNoCancelEnum> dialog = new ButtonMessageDialog<ButtonEnumerations.YesNoCancelEnum>("Warning", "You may have unsaved changes. Save changes?", buttonGroup);
113 buttonGroup.addCallback(new Callback<ButtonEnumerations.YesNoCancelEnum>() {
114
115 @Override
116 public void exec(ButtonEnumerations.YesNoCancelEnum result) {
117 switch (result) {
118 case YES:
119 dialog.hide();
120 fireUpdateEvent(okToChange);
121 break;
122 case NO:
123 dialog.hide();
124 resetModel();
125 needToLoadOldModel = true;
126 resetFieldInteractionFlag();
127 okToChange.exec(true);
128 break;
129 case CANCEL:
130 okToChange.exec(false);
131 dialog.hide();
132
133 HistoryManager.logHistoryChange();
134 break;
135 }
136 }
137 });
138 dialog.show();
139 } else {
140 okToChange.exec(true);
141 }
142 } else {
143 okToChange.exec(false);
144 }
145 }
146 });
147 } else {
148 processBeforeShow = true;
149 }
150 }
151
152 protected void fireUpdateEvent(final Callback<Boolean> okToChange) {
153 eventBus.fireEvent(new UpdateEvent(okToChange));
154 }
155
156 protected void resetModel() {
157 programModel.resetRoot();
158 }
159
160 protected void resetFieldInteractionFlag() {
161 View currentView = getCurrentView();
162 if (currentView instanceof Section) {
163 ((Section) currentView).resetFieldInteractionFlags();
164 }
165 }
166
167
168
169
170 private void initializeModel() {
171 setDefaultModelId(ProgramConstants.PROGRAM_MODEL_ID);
172 registerModel(ProgramConstants.PROGRAM_MODEL_ID, new ModelProvider<DataModel>() {
173 @Override
174 public void requestModel(final ModelRequestCallback<DataModel> callback) {
175 if (programModel.getRoot() == null || programModel.getRoot().size() == 0) {
176 loadModel(callback);
177 } else {
178 callback.onModelReady(programModel);
179 }
180 }
181 });
182 }
183
184
185 @Override
186 public void requestModel(Class modelType, ModelRequestCallback callback) {
187 if (modelType == ReferenceModel.class) {
188 ReferenceModel referenceModel = new ReferenceModel();
189 referenceModel.setReferenceId(ProgramUtils.getProgramId(programModel));
190 referenceModel.setReferenceTypeKey(ProgramConstants.MAJOR_REFERENCE_TYPE_ID);
191 referenceModel.setReferenceType(ProgramConstants.MAJOR_LU_TYPE_ID);
192 Map<String, String> attributes = new HashMap<String, String>();
193 attributes.put("name", getStringProperty("name"));
194 referenceModel.setReferenceAttributes(attributes);
195 callback.onModelReady(referenceModel);
196 } else {
197 super.requestModel(modelType, callback);
198 }
199 }
200
201
202
203
204
205
206
207 protected void loadModel(final ModelRequestCallback<DataModel> callback) {
208 programRemoteService.getData(getViewContext().getId(), new AbstractCallback<Data>(ProgramProperties.get().common_retrievingData()) {
209
210 @Override
211 public void onFailure(Throwable caught) {
212 super.onFailure(caught);
213 callback.onRequestFail(caught);
214 }
215
216 @Override
217 public void onSuccess(Data result) {
218 super.onSuccess(result);
219 programModel.setRoot(result);
220 setHeaderTitle();
221 callback.onModelReady(programModel);
222 }
223 });
224 }
225
226 private void setModelData() {
227 setHeaderTitle();
228 setStatus();
229 configurer.applyPermissions();
230
231 if (needToLoadOldModel) {
232 needToLoadOldModel = false;
233 } else {
234 String id = ProgramUtils.getProgramId(programModel);
235 if (null != id) {
236
237 ViewContext docContext = new ViewContext();
238 docContext.setId(id);
239 docContext.setIdType(IdType.OBJECT_ID);
240 String pgmType = getStringProperty(ProgramConstants.TYPE);
241 docContext.setAttribute(ProgramConstants.TYPE, pgmType + '/' + ProgramSections.PROGRAM_DETAILS_VIEW);
242 RecentlyViewedHelper.addDocument(getProgramName(),
243 HistoryManager.appendContext(getProgramViewLocation(pgmType), docContext));
244 }
245 eventBus.fireEvent(new ModelLoadedEvent(programModel));
246 onModelLoadedEvent();
247 }
248 }
249
250 private String getProgramViewLocation(String pgmType) {
251 if (ProgramClientConstants.MAJOR_PROGRAM.equals(pgmType)) {
252 return AppLocations.Locations.VIEW_PROGRAM.getLocation();
253 } else if (ProgramClientConstants.CORE_PROGRAM.equals(pgmType)) {
254 return AppLocations.Locations.VIEW_CORE_PROGRAM.getLocation();
255 } else if (ProgramClientConstants.CREDENTIAL_PROGRAM_TYPES.contains(pgmType)) {
256 return AppLocations.Locations.VIEW_BACC_PROGRAM.getLocation();
257 }
258 return null;
259 }
260
261 protected void setStatus() {
262 statusLabel.setText(ProgramProperties.get().common_status(getStringProperty(ProgramConstants.STATE)));
263 }
264
265 public String getProgramName() {
266 String name = getStringProperty(ProgramConstants.LONG_TITLE);
267 if (name == null) {
268 name = ProgramProperties.get().common_newProgram();
269 }
270 return name;
271 }
272
273
274
275
276
277
278 @Override
279 public void beforeShow(final Callback<Boolean> onReadyCallback) {
280 if (programModel.getRoot() == null) {
281 loadModel(new ModelRequestCallback<DataModel>() {
282 @Override
283 public void onModelReady(DataModel model) {
284 if (loadMetadataCondition()) {
285 loadMetadata(onReadyCallback);
286 } else {
287
288 onReadyCallback.exec(true);
289 }
290 }
291
292 @Override
293 public void onRequestFail(Throwable cause) {
294 GWT.log(cause.getMessage());
295 }
296 });
297 } else {
298 afterMetadataLoaded(onReadyCallback);
299 }
300 }
301
302
303
304
305
306
307 protected boolean loadMetadataCondition() {
308 return lastLoadedStatus == null || ProgramStatus.of(programModel) != lastLoadedStatus;
309 }
310
311
312
313
314
315
316 protected void loadMetadata(final Callback<Boolean> onReadyCallback) {
317 Map<String, String> idAttributes = new HashMap<String, String>();
318 ViewContext viewContext = getViewContext();
319 IdType idType = viewContext.getIdType();
320 String viewContextId = null;
321 if (idType != null) {
322 idAttributes.put(IdAttributes.ID_TYPE, idType.toString());
323 viewContextId = viewContext.getId();
324 if (idType == IdType.COPY_OF_OBJECT_ID) {
325 viewContextId = null;
326 }
327 }
328 if (programModel.getRoot() != null) {
329 ProgramStatus programStatus = ProgramStatus.of(programModel);
330 idAttributes.put(DtoConstants.DTO_STATE, programStatus.getValue());
331 if (programStatus.getNextStatus() != null) {
332 idAttributes.put(DtoConstants.DTO_NEXT_STATE, programStatus.getNextStatus().getValue());
333 }
334 }
335 programRemoteService.getMetadata(viewContextId, idAttributes, new AbstractCallback<Metadata>() {
336
337 @Override
338 public void onSuccess(Metadata result) {
339 super.onSuccess(result);
340 DataModelDefinition def = new DataModelDefinition(result);
341 programModel.setDefinition(def);
342 lastLoadedStatus = ProgramStatus.of(programModel);
343 afterMetadataLoaded(onReadyCallback);
344 }
345
346 @Override
347 public void onFailure(Throwable caught) {
348 super.onFailure(caught);
349 onReadyCallback.exec(false);
350 }
351 });
352 }
353
354 protected void configureView() {
355 addStyleName("programController");
356 configurer.setModelDefinition(programModel.getDefinition());
357 configurer.configure(this);
358 addContentWidget(statusLabel);
359 setSideBarWidget(sideBar);
360 }
361
362 @Override
363 public void setViewContext(ViewContext viewContext) {
364 super.setViewContext(viewContext);
365 if (viewContext.getId() != null && !viewContext.getId().isEmpty()) {
366 viewContext.setPermissionType(PermissionType.OPEN);
367 } else {
368 viewContext.setPermissionType(PermissionType.INITIATE);
369 }
370 }
371
372
373
374
375
376
377 protected void afterMetadataLoaded(Callback<Boolean> onReadyCallback) {
378 if (!reloadMetadata) {
379 configureView();
380 onReadyCallback.exec(true);
381 reloadMetadata = true;
382 } else {
383 onReadyCallback.exec(true);
384 ProgramUtils.syncMetadata(configurer, programModel.getDefinition());
385 }
386 if (programModel.getRoot() != null) {
387 setModelData();
388 }
389 }
390
391 protected void setHeaderTitle() {
392 String title = getProgramName();
393 this.setContentTitle(title);
394 this.setName(title);
395 }
396
397 protected Widget createCommentPanel() {
398 final CommentTool commentTool = new CommentTool(ProgramSections.COMMENTS, "Comments", "kuali.comment.type.generalRemarks", "Program Comments");
399 commentTool.setController(this);
400 KSButton commentsButton = new KSButton(ProgramProperties.get().comments_button(), KSButtonAbstract.ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
401
402 @Override
403 public void onClick(ClickEvent event) {
404 commentTool.show();
405 }
406 });
407 return commentsButton;
408 }
409
410 protected void doSave() {
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437 protected void updateState(String state, final Callback<Boolean> okCallback) {
438
439 programRemoteService.updateState(programModel.getRoot(), state, new AbstractCallback<DataSaveResult>(ProgramProperties.get().common_savingData()) {
440 @Override
441 public void onSuccess(DataSaveResult result) {
442 if(result.getValidationResults()==null || result.getValidationResults().isEmpty()){
443 super.onSuccess(result);
444 okCallback.exec(true);
445 refreshModelAndView(result);
446 }else{
447
448 super.onSuccess(result);
449
450 isValid(result.getValidationResults(), false, true);
451 ProgramUtils.handleValidationErrorsForSpecializations(result.getValidationResults(), programModel);
452
453 okCallback.exec(false);
454 }
455 }
456
457 });
458
459 }
460
461
462
463
464
465 public void refreshModelAndView(DataSaveResult result){
466 if (result != null) {
467 programModel.setRoot(result.getValue());
468 }
469 setHeaderTitle();
470 setStatus();
471 }
472
473 public DataModel getProgramModel() {
474 return programModel;
475 }
476
477 public void onModelLoadedEvent() {
478 }
479
480 protected String getStringProperty(String key) {
481 return programModel.get(key);
482 }
483
484 protected Data getDataProperty(String key) {
485 return programModel.get(key);
486 }
487
488 public boolean isExportButtonActive() {
489 if (this.getCurrentViewEnum() != null) {
490 if (this.getCurrentViewEnum().equals(ProgramSections.SUMMARY)
491 || this.getCurrentViewEnum().equals(ProgramSections.VIEW_ALL)) {
492 return true;
493 } else {
494 return false;
495 }
496
497 } else {
498 return false;
499 }
500 }
501
502 @Override
503 public ArrayList<ExportElement> getExportElementsFromView() {
504
505 String viewName = null;
506 String sectionTitle = null;
507 View currentView = this.getCurrentView();
508 if (currentView != null) {
509
510 ArrayList<ExportElement> exportElements = new ArrayList<ExportElement>();
511 if (currentView != null && currentView instanceof Section) {
512 Section currentSection = (Section) currentView;
513 List<Section> nestedSections = currentSection.getSections();
514 for (int i = 0; i < nestedSections.size(); i++) {
515 ExportElement sectionExportItem = new ExportElement();
516 ArrayList<ExportElement> subList = null;
517 Section nestedSection = nestedSections.get(i);
518 if (nestedSection != null && nestedSection instanceof SectionView) {
519 SectionView nestedSectionView = (SectionView) nestedSection;
520 viewName = nestedSectionView.getName();
521 sectionTitle = nestedSectionView.getTitle();
522 sectionExportItem.setSectionName(sectionTitle + " " + i + " - " + viewName);
523 sectionExportItem.setViewName(sectionTitle + " " + i + " - " + viewName);
524 subList = ExportUtils.getExportElementsFromView(nestedSectionView, subList, viewName, sectionTitle);
525 if (subList != null && subList.size()> 0) {
526 sectionExportItem.setSubset(subList);
527 exportElements.add(sectionExportItem);
528 }
529 }
530 }
531 }
532 return exportElements;
533
534 } else {
535
536 }
537 return null;
538
539 }
540 }