1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.ui.client.mvc;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.kuali.student.common.assembly.data.Data;
25 import org.kuali.student.common.rice.authorization.PermissionType;
26 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
27 import org.kuali.student.common.ui.client.application.ViewContext;
28 import org.kuali.student.common.ui.client.configurable.mvc.LayoutController;
29 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
30 import org.kuali.student.common.ui.client.mvc.breadcrumb.BreadcrumbSupport;
31 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
32 import org.kuali.student.common.ui.client.mvc.history.HistorySupport;
33 import org.kuali.student.common.ui.client.mvc.history.NavigationEvent;
34 import org.kuali.student.common.ui.client.reporting.ReportExport;
35 import org.kuali.student.common.ui.client.security.AuthorizationCallback;
36 import org.kuali.student.common.ui.client.security.RequiresAuthorization;
37 import org.kuali.student.common.ui.client.service.GwtExportRpcService;
38 import org.kuali.student.common.ui.client.service.GwtExportRpcServiceAsync;
39 import org.kuali.student.common.ui.client.util.ExportElement;
40 import org.kuali.student.common.ui.client.util.ExportUtils;
41 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
42 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
43
44 import com.google.gwt.core.client.GWT;
45 import com.google.gwt.event.shared.HandlerManager;
46 import com.google.gwt.event.shared.HandlerRegistration;
47 import com.google.gwt.event.shared.GwtEvent.Type;
48 import com.google.gwt.user.client.Window;
49 import com.google.gwt.user.client.ui.Composite;
50 import com.google.gwt.user.client.ui.Widget;
51
52
53
54
55
56
57
58 public abstract class Controller extends Composite implements HistorySupport, BreadcrumbSupport, ReportExport{
59 public static final Callback<Boolean> NO_OP_CALLBACK = new Callback<Boolean>() {
60 @Override
61 public void exec(Boolean result) {
62
63 }
64 };
65
66 protected Controller parentController = null;
67 private View currentView = null;
68 private Enum<?> currentViewEnum = null;
69 private String defaultModelId = null;
70 protected ViewContext context = new ViewContext();
71 private final Map<String, ModelProvider<? extends Model>> models = new HashMap<String, ModelProvider<? extends Model>>();
72 private boolean fireNavEvents = true;
73 private HandlerManager applicationEventHandlers = new HandlerManager(this);
74 private GwtExportRpcServiceAsync reportExportRpcService = GWT.create(GwtExportRpcService.class);
75
76 protected Controller() {
77 }
78
79
80
81
82
83
84
85
86 public <V extends Enum<?>> void showView(final V viewType){
87 this.showView(viewType, NO_OP_CALLBACK);
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public <V extends Enum<?>> void showView(final V viewType, final Callback<Boolean> onReadyCallback) {
111 GWT.log("showView " + viewType.toString(), null);
112 getView(viewType, new Callback<View>(){
113
114 @Override
115 public void exec(View result) {
116 View view = result;
117 if (view == null) {
118 onReadyCallback.exec(false);
119
120 }
121 beginShowView(view, viewType, onReadyCallback);
122
123 }},null);
124 }
125
126 private <V extends Enum<?>> void beginShowView(final View view, final V viewType, final Callback<Boolean> onReadyCallback){
127 beforeViewChange(viewType, new Callback<Boolean>(){
128
129 @Override
130 public void exec(Boolean result) {
131 if(result){
132 boolean requiresAuthz = (view instanceof RequiresAuthorization) && ((RequiresAuthorization)view).isAuthorizationRequired();
133
134 if (requiresAuthz){
135
136
137
138 ((RequiresAuthorization)view).checkAuthorization(new AuthorizationCallback(){
139 public void isAuthorized() {
140 finalizeShowView(view, viewType, onReadyCallback);
141 }
142
143 public void isNotAuthorized(String msg) {
144 Window.alert(msg);
145 onReadyCallback.exec(false);
146 }
147 });
148 } else {
149 GWT.log("Not Requiring Auth.", null);
150 finalizeShowView(view, viewType, onReadyCallback);
151 }
152 }
153 else{
154 onReadyCallback.exec(false);
155 }
156
157 }
158 });
159 }
160
161 private <V extends Enum<?>> void finalizeShowView(final View view, final V viewType, final Callback<Boolean> onReadyCallback){
162 if (((currentView == null) || currentView.beforeHide()) && view != null) {
163 view.beforeShow(new Callback<Boolean>() {
164 @Override
165 public void exec(Boolean result) {
166 if (!result) {
167 GWT.log("showView: beforeShow yielded false " + viewType, null);
168 onReadyCallback.exec(false);
169 } else {
170 if (currentView != null) {
171 hideView(currentView);
172 }
173
174 currentViewEnum = viewType;
175 currentView = view;
176 GWT.log("renderView " + viewType.toString(), null);
177 if(fireNavEvents){
178 fireNavigationEvent();
179 }
180 renderView(view);
181 onReadyCallback.exec(true);
182
183 }
184 }
185 });
186 } else {
187 onReadyCallback.exec(false);
188 GWT.log("Current view canceled hide action", null);
189 }
190 }
191
192 protected void fireNavigationEvent() {
193
194
195
196 fireApplicationEvent(new NavigationEvent(Controller.this));
197
198
199 }
200
201
202
203
204
205
206 public View getCurrentView() {
207 return currentView;
208 }
209
210 public Enum<?> getCurrentViewEnum() {
211 return currentViewEnum;
212 }
213
214 public void setCurrentViewEnum(Enum<?> currentViewEnum) {
215 this.currentViewEnum = currentViewEnum;
216 }
217
218
219
220
221
222
223
224
225
226
227 public void setParentController(Controller controller) {
228 parentController = controller;
229 }
230
231
232
233
234
235
236
237 public Controller getParentController() {
238 if (parentController == null) {
239 parentController = Controller.findController(this);
240 }
241 return parentController;
242 }
243
244
245
246
247
248
249
250
251 public static Controller findController(Widget w) {
252 Controller result = null;
253 while (true) {
254 w = w.getParent();
255 if (w == null) {
256 break;
257 } else if (w instanceof Controller) {
258 result = (Controller) w;
259 break;
260 } else if (w instanceof View) {
261
262
263 result = ((View) w).getController();
264 break;
265 }
266 }
267 return result;
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282 @SuppressWarnings("unchecked")
283 public void requestModel(final Class modelType, final ModelRequestCallback callback) {
284 requestModel((modelType == null) ? null : modelType.getName(), callback);
285 }
286
287 @SuppressWarnings("unchecked")
288 public void requestModel(final String modelId, final ModelRequestCallback callback) {
289 String id = (modelId == null) ? defaultModelId : modelId;
290
291 ModelProvider<? extends Model> p = models.get(id);
292 if (p != null) {
293 p.requestModel(callback);
294 } else if (getParentController() != null) {
295 parentController.requestModel(modelId, callback);
296 } else {
297 if (callback != null) {
298 callback.onRequestFail(new RuntimeException("The requested model was not found: " + modelId));
299 }
300 }
301 }
302
303 @SuppressWarnings("unchecked")
304 public void requestModel(final ModelRequestCallback callback) {
305 requestModel((String)null, callback);
306 }
307
308 public <T extends Model> void registerModel(String modelId, ModelProvider<T> provider) {
309 models.put(modelId, provider);
310 }
311
312 public String getDefaultModelId() {
313 return defaultModelId;
314 }
315 public void setDefaultModelId(String defaultModelId) {
316 this.defaultModelId = defaultModelId;
317 }
318
319
320
321
322
323
324
325
326
327
328 @SuppressWarnings("unchecked")
329 public HandlerRegistration addApplicationEventHandler(Type type, ApplicationEventHandler handler) {
330 if ((handler instanceof UncheckedApplicationEventHandler) && (getParentController() != null)) {
331 return parentController.addApplicationEventHandler(type, handler);
332 }
333 return applicationEventHandlers.addHandler(type, handler);
334 }
335
336
337
338
339
340
341 @SuppressWarnings("unchecked")
342 public void fireApplicationEvent(ApplicationEvent event) {
343
344
345 if ((event instanceof UncheckedApplicationEvent) && (getParentController() != null)) {
346 parentController.fireApplicationEvent(event);
347 }
348
349 applicationEventHandlers.fireEvent(event);
350
351 }
352
353
354
355
356
357
358 protected abstract void renderView(View view);
359
360
361
362
363
364
365 protected abstract void hideView(View view);
366
367
368
369
370
371
372
373
374
375 protected <V extends Enum<?>> void getView(V viewType, Callback<View> callback, Map<String, String> tokenMap){
376 getView(viewType, callback);
377 }
378
379
380
381
382
383
384
385
386 protected abstract <V extends Enum<?>> void getView(V viewType, Callback<View> callback);
387
388
389
390
391
392
393
394 public void beforeViewChange(Enum<?> viewChangingTo, Callback<Boolean> okToChangeCallback) {
395 okToChangeCallback.exec(true);
396 }
397
398
399
400
401 public abstract void showDefaultView(Callback<Boolean> onReadyCallback);
402
403 public abstract Enum<?> getViewEnumValue(String enumValue);
404
405
406
407
408
409
410
411 @Override
412 public String collectHistory(String historyStack) {
413 String token = getHistoryToken();
414 historyStack = historyStack + "/" + token;
415
416 if(currentView != null){
417 String tempHistoryStack = historyStack;
418 historyStack = currentView.collectHistory(historyStack);
419
420
421 if(historyStack == null){
422 historyStack = tempHistoryStack;
423 }
424 else if(historyStack != null && historyStack.isEmpty()){
425 historyStack = tempHistoryStack;
426 }
427 }
428 return historyStack;
429 }
430
431 protected String getHistoryToken() {
432 String historyToken = "";
433 if (currentViewEnum != null) {
434 historyToken = currentViewEnum.toString();
435 if(currentView != null && currentView instanceof Controller
436 && ((Controller)currentView).getViewContext() != null){
437 ViewContext context = ((Controller) currentView).getViewContext();
438 historyToken = HistoryManager.appendContext(historyToken, context);
439 }
440
441 }
442 return historyToken;
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457 @Override
458 public void onHistoryEvent(String historyStack) {
459 final String nextHistoryStack = HistoryManager.nextHistoryStack(historyStack);
460 String[] tokens = HistoryManager.splitHistoryStack(nextHistoryStack);
461 if (tokens.length >= 1 && tokens[0] != null && !tokens[0].isEmpty()) {
462 final Map<String, String> tokenMap = HistoryManager.getTokenMap(tokens[0]);
463
464 String viewEnumString = tokenMap.get("view");
465 if (viewEnumString != null) {
466 final Enum<?> viewEnum = getViewEnumValue(viewEnumString);
467
468 if (viewEnum != null) {
469 getView(viewEnum, new Callback<View>(){
470
471 @Override
472 public void exec(View result) {
473 View theView = result;
474 boolean sameContext = true;
475 if(theView instanceof Controller){
476
477 ViewContext newContext = new ViewContext();
478 Iterator<String> tokenIt = tokenMap.keySet().iterator();
479 while(tokenIt.hasNext()){
480 String key = tokenIt.next();
481 if(key.equals(ViewContext.ID_ATR)){
482 newContext.setId(tokenMap.get(ViewContext.ID_ATR));
483 }
484 else if(key.equals(ViewContext.ID_TYPE_ATR)){
485 newContext.setIdType(tokenMap.get(ViewContext.ID_TYPE_ATR));
486 }
487
488 else if(!key.equals("view")){
489 newContext.setAttribute(key, tokenMap.get(key));
490 }
491 }
492
493 ViewContext viewContext = ((Controller) theView).getViewContext();
494 if(viewContext.compareTo(newContext) != 0){
495 ((Controller) theView).setViewContext(newContext);
496 sameContext = false;
497 }
498 }
499 if (currentViewEnum == null || !viewEnum.equals(currentViewEnum)
500 || !sameContext) {
501 beginShowView(theView, viewEnum, new Callback<Boolean>() {
502 @Override
503 public void exec(Boolean result) {
504 if (result) {
505 currentView.onHistoryEvent(nextHistoryStack);
506 }
507 }
508 });
509 } else if (currentView != null) {
510 currentView.onHistoryEvent(nextHistoryStack);
511 }
512 }
513 },tokenMap);
514
515 }
516 }
517 }
518 else{
519 this.showDefaultView(new Callback<Boolean>(){
520
521 @Override
522 public void exec(Boolean result) {
523 if(result){
524 currentView.onHistoryEvent(nextHistoryStack);
525 }
526
527 }
528 });
529 }
530
531 }
532
533
534
535
536
537
538
539
540 public void setViewContext(ViewContext viewContext){
541 this.context = viewContext;
542 }
543
544 public ViewContext getViewContext() {
545 return this.context;
546 }
547
548 public void resetCurrentView(){
549 currentView = null;
550 }
551
552
553
554
555
556
557
558
559 @Override
560 public void doReportExport(List<ExportElement> exportElements, final String format, final String reportTitle) {
561
562 final BlockingTask loadDataTask = new BlockingTask("Generating Export File");
563
564 DataModel dataModel = getExportDataModel();
565 Data modelDataObject = null;
566 if (dataModel != null) {
567 modelDataObject = dataModel.getRoot();
568 }
569
570
571
572 KSBlockingProgressIndicator.addTask(loadDataTask);
573
574 reportExportRpcService.reportExport(exportElements, modelDataObject, getExportTemplateName(), format, reportTitle, new KSAsyncCallback<String>() {
575 @Override
576 public void onSuccess(String result) {
577
578
579
580 String baseUrl = GWT.getHostPageBaseURL();
581 baseUrl = baseUrl.replaceFirst(GWT.getModuleName() + "/", "");
582
583 KSBlockingProgressIndicator.removeTask(loadDataTask);
584
585 Window.open(baseUrl + "exportDownloadHTTPServlet?exportId="+result + "&format=" + format, "", "");
586 }
587
588 @Override
589 public void handleFailure(Throwable caught) {
590 KSBlockingProgressIndicator.removeTask(loadDataTask);
591 super.handleFailure(caught);
592 }
593
594 });
595
596
597
598 }
599
600
601 @Override
602 public DataModel getExportDataModel() {
603 return null;
604 }
605
606
607
608
609
610 @Override
611 public String getExportTemplateName() {
612 return exportTemplateName;
613 }
614
615 @Override
616 public List<ExportElement> getExportElementsFromView() {
617 String viewName = null;
618 View currentView = this.getCurrentView();
619 if (currentView != null) {
620
621 ArrayList<ExportElement> exportElements = null;
622
623 if (currentView != null && currentView instanceof SectionView) {
624 viewName = currentView.getName();
625 exportElements = ExportUtils.getExportElementsFromView((SectionView)currentView, exportElements, viewName, "Sectionname");
626 return exportElements;
627 } else {
628
629 }
630 } else {
631
632 }
633 return null;
634 }
635 }