View Javadoc

1   /**
2    * Copyright 2011 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.mobility.admin.controllers;
17  
18  import java.text.SimpleDateFormat;
19  import java.util.Collections;
20  import java.util.Date;
21  import java.util.Iterator;
22  import java.util.List;
23  
24  import javax.servlet.http.HttpServletRequest;
25  
26  import org.kuali.mobility.admin.entity.HomeScreen;
27  import org.kuali.mobility.admin.entity.HomeTool;
28  import org.kuali.mobility.admin.entity.Tool;
29  import org.kuali.mobility.admin.service.AdminService;
30  import org.kuali.mobility.news.entity.NewsSource;
31  import org.kuali.mobility.news.entity.NewsSourceDBImpl;
32  import org.kuali.mobility.news.service.NewsService;
33  import org.kuali.mobility.notification.entity.Notification;
34  import org.kuali.mobility.notification.service.NotificationService;
35  import org.kuali.mobility.security.authz.entity.AclExpression;
36  import org.springframework.beans.factory.annotation.Autowired;
37  import org.springframework.beans.propertyeditors.CustomDateEditor;
38  import org.springframework.stereotype.Controller;
39  import org.springframework.ui.Model;
40  import org.springframework.validation.BindingResult;
41  import org.springframework.validation.Errors;
42  import org.springframework.web.bind.WebDataBinder;
43  import org.springframework.web.bind.annotation.InitBinder;
44  import org.springframework.web.bind.annotation.ModelAttribute;
45  import org.springframework.web.bind.annotation.PathVariable;
46  import org.springframework.web.bind.annotation.RequestMapping;
47  import org.springframework.web.bind.annotation.RequestMethod;
48  import org.springframework.web.bind.annotation.RequestParam;
49  
50  /**
51   * Controller for performing publishing actions
52   * @author Kuali Mobility Team (mobility.dev@kuali.org)
53   */
54  @Controller 
55  @RequestMapping("/publishing")
56  public class PublishingController {
57      
58      @Autowired
59      private AdminService adminService;
60      
61      @Autowired
62      private NotificationService notificationService;
63      
64      @Autowired
65      private NewsService newsService;
66  
67      /**
68       * The main entry point for publishing. Provides links to more specific publishing tools.
69       * @param uiModel
70       * @return
71       */
72  	@RequestMapping(method = RequestMethod.GET)
73      public String publishingHome(Model uiModel) {
74      	return "publishing/index";
75      }
76      
77      /**
78       * The main entry point for publishing. Provides links to more specific publishing tools.
79       * @param uiModel
80       * @return
81       */
82  	@RequestMapping(value = "index", method = RequestMethod.GET)
83      public String index(Model uiModel) {
84      	return "publishing/index";
85      }
86  	
87  	//----------------Tools------------------
88  
89  	/**
90  	 * Entry point for publishing Tools.  Lists currently defined Tools.
91  	 * @param uiModel
92  	 * @return the tool publishing entry page
93  	 */
94      @RequestMapping(value = "tool", method = RequestMethod.GET)
95      public String tool(Model uiModel) {
96      	List<Tool> tools = adminService.getAllTools();
97      	Collections.sort(tools);
98      	uiModel.addAttribute("tools", tools);
99      	return "publishing/tool";
100     }
101     
102     /**
103      * Create a new Tool
104      * @param uiModel
105      * @return the edit tool page
106      */
107     @RequestMapping(value = "tool/new", method = RequestMethod.GET)
108     public String newTool(Model uiModel) {
109         Tool tool = new Tool();
110         tool.setPublishingPermission(new AclExpression());
111         tool.setViewingPermission(new AclExpression());
112     	uiModel.addAttribute("tool", tool);
113     	return "publishing/editTool";
114     }
115     
116     /**
117      * Edit an existing Tool
118      * @param uiModel
119      * @param toolId id of the Tool to edit
120      * @return the edit tool page
121      */
122     @RequestMapping(value = "tool/edit/{toolId}", method = RequestMethod.GET)
123     public String editTool(Model uiModel, @PathVariable("toolId") long toolId) {
124     	Tool tool = adminService.getToolById(toolId);
125     	uiModel.addAttribute("tool", tool);
126     	return "publishing/editTool";
127     }
128     
129     /**
130      * Delete a Tool
131      * @param uiModel
132      * @param toolId id of the Tool to delete
133      * @return back to the tool publishing entry page
134      */
135     @RequestMapping(value = "tool/delete/{toolId}", method = RequestMethod.GET)
136     public String deleteTool(Model uiModel, @PathVariable("toolId") long toolId) {
137     	adminService.deleteToolById(toolId);
138     	return tool(uiModel);
139     }
140     
141     /**
142      * Save a Tool
143      * @param uiModel
144      * @param tool the Tool object to save
145      * @param result binding validation result
146      * @return back to the tool publishing entry page
147      */
148     @RequestMapping(value = "tool/edit", method = RequestMethod.POST)
149     public String editTool(Model uiModel, @ModelAttribute("tool") Tool tool, BindingResult result) {
150     	adminService.saveTool(tool);
151     	return tool(uiModel);
152     }
153     
154   //----------------Layouts------------------
155 
156     /**
157      * The entry point for publishing HomeScreen layouts
158      * @param uiModel
159      * @return the home screen publishing entry page
160      */
161     @RequestMapping(value = "layout", method = RequestMethod.GET)
162     public String layout(Model uiModel) {
163     	uiModel.addAttribute("layouts", adminService.getAllHomeScreens());
164     	return "publishing/layout";
165     }
166     
167     /**
168      * Create a new HomeScreen
169      * @param uiModel
170      * @return the home screen editing page
171      */
172     @RequestMapping(value = "layout/new", method = RequestMethod.GET)
173     public String newLayout(Model uiModel) {
174     	uiModel.addAttribute("layout", new HomeScreen());
175     	uiModel.addAttribute("availableTools", adminService.getAllTools());
176     	return "publishing/editLayout";
177     }
178     
179     /**
180      * Edit an existing HomeScreen
181      * @param uiModel
182      * @param layoutId the id of the HomeScreen to edit
183      * @return the home screen editing page
184      */
185     @RequestMapping(value = "layout/edit/{layoutId}", method = RequestMethod.GET)
186     public String editLayout(Model uiModel, @PathVariable("layoutId") long layoutId) {
187     	HomeScreen layout = adminService.getHomeScreenById(layoutId);
188     	Collections.sort(layout.getHomeTools());
189     	uiModel.addAttribute("layout", layout);
190     	uiModel.addAttribute("availableTools", adminService.getAllTools());
191     	return "publishing/editLayout";
192     }
193     
194     /**
195      * Save a HomeScreen
196      * @param uiModel
197      * @param homeScreen the HomeScreen to save
198      * @param result binding validation result
199      * @return the home screen publishing entry page
200      */
201     @RequestMapping(value = "layout/edit", method = RequestMethod.POST)
202     public String editLayout(Model uiModel, @ModelAttribute("layout") HomeScreen homeScreen, BindingResult result) {
203     	int index = 0;
204     	for (HomeTool ht : homeScreen.getHomeTools()) {
205 			ht.setOrder(index++);
206 		}
207     	adminService.saveHomeScreen(homeScreen);
208     	return layout(uiModel);
209     }
210     
211     /**
212      * Delete a HomeScreen
213      * @param uiModel
214      * @param layoutId the id of the HomeScren to delete
215      * @return the home screen publishing entry page
216      */
217     @RequestMapping(value = "layout/delete/{layoutId}", method = RequestMethod.GET)
218     public String deleteLayout(Model uiModel, @PathVariable("layoutId") long layoutId) {
219     	adminService.deleteHomeScreenById(layoutId);
220     	return layout(uiModel);
221     }
222     
223     /**
224      * Associate a Tool with a HomeScreen if it isn't already associated
225      * @param uiModel
226      * @param homeScreen the HomeScreen to which to add the Tool
227      * @param result binding validation result for the HomeScreen
228      * @param toolId the id of the Tool to associate with the HomeSreen
229      * @return the home screen editing page
230      */
231     @RequestMapping(value = "layout/edit", method = RequestMethod.POST, params = "add")
232     public String addTool(Model uiModel, @ModelAttribute("layout") HomeScreen homeScreen, BindingResult result, @RequestParam("toolToAdd") Long toolId) {
233     	Tool tool = adminService.getToolById(toolId);
234     	boolean found = false;
235     	for (HomeTool homeTool : homeScreen.getHomeTools()) {
236     		if (homeTool.getToolId().equals(toolId)) {
237     			found = true;
238     			break;
239     		}
240     	}
241     	if (!found) {
242     		HomeTool homeTool = new HomeTool(homeScreen, tool, homeScreen.getHomeTools().size());
243     		homeScreen.getHomeTools().add(homeTool);
244     	}
245     	Collections.sort(homeScreen.getHomeTools());
246     	uiModel.addAttribute("layout", homeScreen);
247     	uiModel.addAttribute("availableTools", adminService.getAllTools());
248     	return "publishing/editLayout";
249     }
250     
251     /**
252      * Remove a Tool's association with a HomeScreen
253      * @param uiModel
254      * @param homeScreen the HomeScreen from which to remove the Tool association
255      * @param result the binding validation result for the HomeScreen
256      * @param toolId the id of the Tool to remove
257      * @return the home screen editing page
258      */
259     @RequestMapping(value = "layout/edit", method = RequestMethod.POST, params = "remove")
260     public String removeTool(Model uiModel, @ModelAttribute("layout") HomeScreen homeScreen, BindingResult result, @RequestParam("removeId") Long toolId) {
261     	Integer removedOrder = null;
262     	for (Iterator<HomeTool> iter = homeScreen.getHomeTools().iterator(); iter.hasNext();) {
263     		HomeTool homeTool = iter.next();
264     		if (homeTool.getToolId().equals(toolId)) {
265     			removedOrder = homeTool.getOrder();
266     			iter.remove();
267     			break;
268     		}
269     	}
270     	if (removedOrder != null) {
271         	int index = 0;
272         	for (HomeTool ht : homeScreen.getHomeTools()) {
273     			ht.setOrder(index++);
274     		}
275         }
276     	Collections.sort(homeScreen.getHomeTools());
277     	uiModel.addAttribute("layout", homeScreen);
278     	uiModel.addAttribute("availableTools", adminService.getAllTools());
279     	return "publishing/editLayout";
280     }
281     
282     /**
283      * Move a tool up in the Tool list display order
284      * @param uiModel
285      * @param homeScreen the HomeScreen to edit
286      * @param result binding validation result for the HomeScreen
287      * @param toolId the id of the Tool to move
288      * @return the home screen editing page
289      */
290     @RequestMapping(value = "layout/edit", method = RequestMethod.POST, params = "up")
291     public String moveToolUp(Model uiModel, @ModelAttribute("layout") HomeScreen homeScreen, BindingResult result, @RequestParam("removeId") Long toolId) {
292     	HomeTool selectedHomeTool = null;
293     	
294     	for (HomeTool homeTool : homeScreen.getHomeTools()) {
295     		if (homeTool.getToolId().equals(toolId)) {
296     			selectedHomeTool = homeTool;
297     			break;
298     		}
299     	}
300     	if (selectedHomeTool != null && selectedHomeTool.getOrder() > 0) {
301     		for (HomeTool ht : homeScreen.getHomeTools()) {
302     			if (ht.getOrder() == selectedHomeTool.getOrder() - 1) {
303     				int swap = ht.getOrder();
304     				ht.setOrder(selectedHomeTool.getOrder());
305     				selectedHomeTool.setOrder(swap);
306     				break;
307     			}
308     		}
309     	}
310     	Collections.sort(homeScreen.getHomeTools());
311     	uiModel.addAttribute("layout", homeScreen);
312     	uiModel.addAttribute("availableTools", adminService.getAllTools());
313     	return "publishing/editLayout";
314     }
315     
316     /**
317      * Move a tool down in the Tool list display order
318      * @param uiModel
319      * @param homeScreen the HomeScreen to edit
320      * @param result binding validation result for the HomeScreen
321      * @param toolId the id of the Tool to move
322      * @return the home screen editing page
323      */
324     @RequestMapping(value = "layout/edit", method = RequestMethod.POST, params = "down")
325     public String moveToolDown(Model uiModel, @ModelAttribute("layout") HomeScreen homeScreen, BindingResult result, @RequestParam("removeId") Long toolId) {
326     	HomeTool selectedHomeTool = null;
327     	
328     	for (HomeTool homeTool : homeScreen.getHomeTools()) {
329     		if (homeTool.getToolId().equals(toolId)) {
330     			selectedHomeTool = homeTool;
331     			break;
332     		}
333     	}
334     	if (selectedHomeTool != null) {
335     		for (HomeTool ht : homeScreen.getHomeTools()) {
336     			if (ht.getOrder() == selectedHomeTool.getOrder() + 1) {
337     				int swap = ht.getOrder();
338     				ht.setOrder(selectedHomeTool.getOrder());
339     				selectedHomeTool.setOrder(swap);
340     				break;
341     			}
342     		}
343     	}
344     	Collections.sort(homeScreen.getHomeTools());
345     	uiModel.addAttribute("layout", homeScreen);
346     	uiModel.addAttribute("availableTools", adminService.getAllTools());
347     	return "publishing/editLayout";
348     }
349     
350     
351     //----------------Notifications------------------
352 
353     /**
354      * the main entry point for notifications
355      * @param uiModel
356      * @return the notifications entry page
357      */
358     @RequestMapping(value = "notifications", method = RequestMethod.GET)
359     public String notifications(Model uiModel) {
360     	uiModel.addAttribute("notifications", notificationService.findAllNotifications());
361     	return "publishing/notifications";
362     }
363 
364     /**
365      * Create or edit a notification
366      * @param id (optional) the id of the notification to edit
367      * @param uiModel
368      * @return the notification edit form
369      */
370     @RequestMapping(value = "notificationForm", method = RequestMethod.GET)
371     public String notificationForm(@RequestParam(value="id", required=false) Long id, Model uiModel) {
372     	Notification n = new Notification();
373     	if (id != null) {
374     		n = notificationService.findNotificationById(id);
375     	}
376     	uiModel.addAttribute("notification", n);
377     	return "publishing/notificationForm";
378     }
379 
380     /**
381      * Edit a notification
382      * @param id the id of the notification to edit
383      * @param uiModel
384      * @return the notification edit form
385      */
386     @RequestMapping(value = "editNotification", method = RequestMethod.GET)
387     public String editNotification(@RequestParam(value="id", required=true) Long id, Model uiModel) {
388     	Notification n = notificationService.findNotificationById(id);
389     	uiModel.addAttribute("notification", n);
390     	return "publishing/notificationForm";
391     }
392 
393     /**
394      * Delete a notification
395      * @param id the id of the notification to delete
396      * @param uiModel
397      * @return the notifications entry page
398      */
399     @RequestMapping(value = "deleteNotification", method = RequestMethod.GET)
400     public String deleteNotification(@RequestParam(value="id", required=true) Long id, Model uiModel) {
401     	notificationService.deleteNotificationById(id);
402     	return "redirect:/publishing/notifications";
403     }
404     
405     /**
406      * Save a notification
407      * @param request
408      * @param uiModel
409      * @param notification the Notification to save
410      * @param result binding validation result
411      * @return the notifications entry page
412      */
413     @RequestMapping(value="notificationSubmit", method = RequestMethod.POST)
414     public String submit(HttpServletRequest request, Model uiModel, @ModelAttribute("notification") Notification notification, BindingResult result) {
415     	if (isValidNotification(notification, result)) {
416     		notificationService.saveNotification(notification);
417         	return "redirect:/publishing/notifications"; 
418         } else {
419         	return "publishing/notificationForm";    	
420         }
421     }
422     
423     @InitBinder
424     public void initBinder(WebDataBinder binder) {
425         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
426         dateFormat.setLenient(false);
427         binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
428     }
429 
430     /**
431      * Validate a Notification
432      * @param notification the Notification to validate
433      * @param result
434      * @return true if valid
435      */
436     private boolean isValidNotification(Notification notification, BindingResult result) {
437     	boolean hasErrors = false;
438     	Errors errors = ((Errors) result);
439     	if (errors.hasFieldErrors("startDate")) {    		
440     		errors.rejectValue("startDate", "", "Please enter a valid start date (empty or YYYY-MM-DD)");
441     		hasErrors = true;    		
442     	}
443     	if (errors.hasFieldErrors("endDate")) {
444     		errors.rejectValue("endDate", "", "Please enter a valid end date (empty or YYYY-MM-DD)");
445     		hasErrors = true;    		
446     	}
447     	if (notification.getMessage() == null || "".equals(notification.getMessage().trim())) {
448     		errors.rejectValue("message", "", "Please enter a message");
449     		hasErrors = true;
450     	}
451     	if (notification.getTitle() == null || "".equals(notification.getTitle().trim())) {
452     		errors.rejectValue("title", "", "Please enter a title");
453     		hasErrors = true;
454     	}
455     	if (notification.getNotificationType() == null) {
456     		notification.setNotificationType(new Long(1));
457     	}
458     	return !hasErrors;
459     }
460     
461   //----------------News------------------
462     /**
463      * The main entry point for News publishing
464      * @param uiModel
465      * @return the news entry page
466      */
467     @RequestMapping(value = "news", method = RequestMethod.GET)
468     public String news(Model uiModel) {
469     	uiModel.addAttribute("sources", newsService.getAllNewsSources());
470     	return "publishing/news";
471     }
472     
473     /**
474      * Create a new NewsSource
475      * @param uiModel
476      * @return the news source editing page
477      */
478     @RequestMapping(value = "news/add", method = RequestMethod.GET)
479     public String editNews(Model uiModel) {
480     	NewsSource source = new NewsSourceDBImpl();
481     	source.setOrder(newsService.getAllNewsSources().size());
482     	source.setActive(true);
483     	uiModel.addAttribute("source", source);
484     	return "publishing/editNews";
485     }
486     
487     /**
488      * Edit an existing NewsSource
489      * @param uiModel
490      * @param id the id of the NewsSource to edit
491      * @return the news source editing page
492      */
493     @RequestMapping(value = "news/edit/{id}", method = RequestMethod.GET)
494     public String editNews(Model uiModel, @PathVariable("id") long id) {
495     	NewsSource newsSource = newsService.getNewsSourceById(id);
496     	uiModel.addAttribute("source", newsSource);
497     	return "publishing/editNews";
498     }
499     
500 //    /**
501 //     * Delete a NewsSource
502 //     * @param uiModel
503 //     * @param id the id of the NewsSource to delete
504 //     * @return the news entry page
505 //     */
506 //    @RequestMapping(value = "news/delete/{id}", method = RequestMethod.GET)
507 //    public String deleteNewsSource(Model uiModel, @PathVariable("id") long id) {
508 //    	newsService.deleteNewsSourcebyId(id);
509 //    	return news(uiModel);
510 //    }
511 //    
512 //    /**
513 //     * Save a NewsSource
514 //     * @param uiModel
515 //     * @param source the NewsSource to save
516 //     * @param result the binding validation result
517 //     * @return the news entry page
518 //     */
519 //    @RequestMapping(value = "news/edit", method = RequestMethod.POST)
520 //    public String editNewsSource(Model uiModel, @ModelAttribute("source") NewsSource source, BindingResult result) {
521 //    	if ("".equals(source.getUrl().trim())) {
522 //    		Errors errors = (Errors)result;
523 //    		errors.rejectValue("url", "", "Please enter a Url to an RSS or Atom feed.");
524 //    		return "publishing/editNews";
525 //    	}
526 //    	source.setUrl(source.getUrl().trim());
527 //    	newsService.saveNewsSource(source);
528 //    	return news(uiModel);
529 //    }
530 //    
531 //    /**
532 //     * Move a news feed up in the display order
533 //     * @param uiModel
534 //     * @param id the id of the NewsSource to move
535 //     * @return the news entry page
536 //     */
537 //    @RequestMapping(value = "news/up/{id}", method = RequestMethod.GET)
538 //    public String moveUp(Model uiModel, @PathVariable("id") long id) {
539 //    	newsService.moveNewsSourceUp(id);
540 //    	return news(uiModel);
541 //    }
542 //    
543 //    /**
544 //     * Move a news feed down in the display order
545 //     * @param uiModel
546 //     * @param id the id of the NewsSource to move
547 //     * @return the news entry page
548 //     */
549 //    @RequestMapping(value = "news/down/{id}", method = RequestMethod.GET)
550 //    public String moveDown(Model uiModel, @PathVariable("id") long id) {
551 //    	newsService.moveNewsSourceDown(id);
552 //    	return news(uiModel);
553 //    }
554 }