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.feedback.controllers;
17  
18  import org.slf4j.Logger;
19  import org.slf4j.LoggerFactory;
20  import org.kuali.mobility.admin.entity.HomeScreen;
21  import org.kuali.mobility.admin.entity.HomeTool;
22  import org.kuali.mobility.admin.entity.Tool;
23  import org.kuali.mobility.admin.service.AdminService;
24  import org.kuali.mobility.feedback.entity.Feedback;
25  import org.kuali.mobility.feedback.entity.FeedbackDeviceType;
26  import org.kuali.mobility.feedback.entity.FeedbackSubject;
27  import org.kuali.mobility.feedback.service.FeedbackDeviceTypeService;
28  import org.kuali.mobility.feedback.service.FeedbackService;
29  import org.kuali.mobility.feedback.service.FeedbackSubjectService;
30  import org.kuali.mobility.security.authz.entity.AclExpression;
31  import org.kuali.mobility.security.user.api.User;
32  import org.kuali.mobility.shared.Constants;
33  import org.springframework.beans.factory.annotation.Autowired;
34  import org.springframework.stereotype.Controller;
35  import org.springframework.ui.Model;
36  import org.springframework.validation.BindingResult;
37  import org.springframework.validation.Errors;
38  import org.springframework.web.bind.annotation.ModelAttribute;
39  import org.springframework.web.bind.annotation.RequestMapping;
40  import org.springframework.web.bind.annotation.RequestMethod;
41  import org.springframework.web.servlet.LocaleResolver;
42  
43  import javax.annotation.Resource;
44  import javax.servlet.http.Cookie;
45  import javax.servlet.http.HttpServletRequest;
46  import java.sql.Timestamp;
47  import java.util.*;
48  
49  @Controller
50  @RequestMapping("/feedback")
51  public class FeedbackController {
52  
53  	private static final Logger LOG = LoggerFactory
54  			.getLogger(FeedbackController.class);
55  
56  	@Autowired
57  	private FeedbackService feedbackService;
58  
59  	@Autowired
60  	private FeedbackSubjectService feedbackSubjectService;
61  
62  	@Autowired
63  	private FeedbackDeviceTypeService feedbackDeviceTypeService;
64  
65  	@Autowired
66  	private AdminService adminService;
67  
68  	/**
69       */
70  	public void setFeedbackService(FeedbackService feedbackService) {
71  		this.feedbackService = feedbackService;
72  	}
73  
74  	@Resource(name = "kmeProperties")
75  	private Properties kmeProperties;
76  
77  	/**
78  	 * A reference to the Spring Locale Resolver
79  	 */
80  	@Resource(name = "localeResolver")
81  	private LocaleResolver localeResolver;
82  
83  	private static final Map<String, String> deviceTypes;
84  	private Map<String, String> subjectList;
85  	private Map<String, String> deviceTypesList;
86  	static {
87  		deviceTypes = new LinkedHashMap<String, String>();
88  		deviceTypes.put("feedback.default", "feedback.default");
89  		deviceTypes.put("feedback.computer", "feedback.computer");
90  		deviceTypes.put("feedback.android", "feedback.android");
91  		deviceTypes.put("feedback.blackberry", "feedback.blackberry");
92  		deviceTypes.put("feedback.ipad", "feedback.ipad");
93  		deviceTypes.put("feedback.iphone", "feedback.iphone");
94  		deviceTypes.put("feedback.ipod", "feedback.ipod");
95  		deviceTypes.put("feedback.windowsMobile", "feedback.windowsMobile");
96  		deviceTypes.put("feedback.other", "feedback.other");
97  	}
98  
99  	private void getFeedbackSubjectList() {
100 		List<FeedbackSubject> feedbacksubjects = feedbackSubjectService
101 				.getFeedbackSubjects();
102 		subjectList = new LinkedHashMap<String, String>();
103 		for (FeedbackSubject feedbackSubject : feedbacksubjects) {
104 			subjectList.put(feedbackSubject.getSubjectKey(),
105 					feedbackSubject.getSubjectValue());
106 		}
107 	}
108 
109 	private void getFeedbackDeviceTypeList() {
110 		List<FeedbackDeviceType> feedbackDevices = feedbackDeviceTypeService
111 				.getFeedbackDviceType();
112 		deviceTypesList = new LinkedHashMap<String, String>();
113 		for (FeedbackDeviceType feedbackDeviceType : feedbackDevices) {
114 			deviceTypesList.put(feedbackDeviceType.getSubjectDeviceKey(),
115 					feedbackDeviceType.getSubjectDeviceValue());
116 		}
117 
118 	}
119 
120 	@RequestMapping(value = "/js/feedback.js")
121 	public String getJavaScript(Model uiModel) {
122 		return "ui3/feedback/js/feedback";
123 	}
124 
125 	@RequestMapping(method = RequestMethod.GET)
126 	public String getList(Model uiModel, HttpServletRequest request) {
127 		User user = (User) request.getSession().getAttribute(
128 				Constants.KME_USER_KEY);
129 		getFeedbackSubjectList();
130 		getFeedbackDeviceTypeList();
131 		uiModel.addAttribute("subjectList", subjectList);
132 		uiModel.addAttribute("deviceTypes", deviceTypesList);
133 		Feedback feedback = new Feedback();
134 		if (user != null && user.getEmail() != null) { // pre populate email
135 			feedback.setEmail(user.getEmail());
136 		}
137 		uiModel.addAttribute("feedback", feedback);
138 
139 		uiModel.addAttribute("tools", getHomeToolList(request));
140 
141 		if ("3".equalsIgnoreCase(getKmeProperties().getProperty(
142 				"kme.uiVersion", "classic"))) {
143 			return "ui3/feedback/index";
144 		}
145 
146 		return "feedback/form";
147 	}
148 
149 	@RequestMapping(method = RequestMethod.POST)
150 	public String submitFeedback(Model uiModel,
151 			@ModelAttribute("feedback") Feedback feedback,
152 			BindingResult result, HttpServletRequest request) {
153 		// feedback.setPostedTimestamp(new
154 		// Timestamp(System.currentTimeMillis()));
155 		Locale locale = this.localeResolver.resolveLocale(request);
156 
157 		User user = (User) request.getSession().getAttribute(
158 				Constants.KME_USER_KEY);
159 		if (user != null) {
160 			if (user.getLoginName() != null)
161 				feedback.setUserId(user.getLoginName());
162 			if (feedback.getCampus() == null
163 					|| feedback.getCampus().trim().isEmpty())
164 				feedback.setCampus(user.getViewCampus());
165 		}
166 
167 		if (isValidFeedback(feedback, result)) {
168 			feedbackService.saveFeedback(feedback, locale);
169 
170 			if ("3".equalsIgnoreCase(getKmeProperties().getProperty(
171 					"kme.uiVersion", "classic"))) {
172 				return "ui3/feedback/index";
173 			}
174 
175 			return "feedback/thanks";
176 		} else {
177 			getFeedbackSubjectList();
178 			getFeedbackDeviceTypeList();
179 			uiModel.addAttribute("subjectList", subjectList);
180 			uiModel.addAttribute("deviceTypes", deviceTypesList);
181 
182 			if ("3".equalsIgnoreCase(getKmeProperties().getProperty(
183 					"kme.uiVersion", "classic"))) {
184 				return "ui3/feedback/index";
185 			}
186 
187 			return "feedback/form";
188 		}
189 	}
190 
191 	private boolean isValidFeedback(Feedback f, BindingResult result) {
192 		boolean hasErrors = false;
193 		Errors errors = ((Errors) result);
194 		if (f.getNoteText() == null || "".equals(f.getNoteText().trim())) {
195 			errors.rejectValue("noteText", "",
196 					"Please type some feedback into the input box.");
197 			hasErrors = true;
198 		} else if (f.getNoteText().length() > 2000) {
199 			errors.rejectValue("noteText", "",
200 					"Error: Feedback must be less than 2000 characters.");
201 			hasErrors = true;
202 		}
203 		if (f.getDeviceType() == null || f.getDeviceType().equals("")) {
204 			errors.rejectValue("deviceType", "", "Please select a device type.");
205 			hasErrors = true;
206 		} else if (deviceTypes.get(f.getDeviceType()) == null) {
207 			errors.rejectValue("deviceType", "",
208 					"Error: Please select a valid device type.");
209 			hasErrors = true;
210 		}
211 		return !hasErrors;
212 	}
213 
214 	private List<HomeTool> getHomeToolList(HttpServletRequest request) {
215 		List<HomeTool> userTools = new ArrayList<HomeTool>();
216 
217 		int myState = 0;
218 		Cookie cks[] = request.getCookies();
219 		if (cks != null) {
220 			for (Cookie c : cks) {
221 				if (c.getName().equals("native")) {
222 					if ("yes".equals(c.getValue())) {
223 						myState |= Tool.NATIVE;
224 					} else {
225 						myState |= Tool.NON_NATIVE;
226 					}
227 				}
228 				if (c.getName().equals("platform")) {
229 					if ("iOS".equals(c.getValue())) {
230 						myState |= Tool.IOS;
231 					} else if ("Android".equals(c.getValue())) {
232 						myState |= Tool.ANDROID;
233 					} else if ("WindowsMobile".equals(c.getValue())) {
234 						myState |= Tool.WINDOWS_PHONE;
235 					} else if ("Blackberry".equals(c.getValue())) {
236 						myState |= Tool.BLACKBERRY;
237 					}
238 				}
239 			}
240 		}
241 
242 		User user = (User) request.getSession().getAttribute(
243 				Constants.KME_USER_KEY);
244 
245 		String alias = "PUBLIC";
246 		if (request.getParameter("alias") != null) {
247 			alias = request.getParameter("alias").toUpperCase();
248 		}
249 		if (user != null && user.getViewCampus() != null) {
250 			alias = user.getViewCampus();
251 		}
252 
253 		HomeScreen home = getAdminService().getHomeScreenByAlias(alias);
254 		if (home == null) {
255 			LOG.debug("Home screen was null, getting PUBLIC screen.");
256 			home = getAdminService().getHomeScreenByAlias("PUBLIC");
257 		}
258 
259 		List<HomeTool> copy;
260 		if (home == null) {
261 			LOG.error("Home screen object still null when it should not be.");
262 			copy = new ArrayList<HomeTool>();
263 		} else {
264 			copy = new ArrayList<HomeTool>(home.getHomeTools());
265 		}
266 		Collections.sort(copy);
267 
268 		for (HomeTool homeTool : copy) {
269 			Tool tool = homeTool.getTool();
270 
271 			AclExpression viewingPermission = tool.getViewingPermission();
272 			if (viewingPermission != null
273 					&& viewingPermission.getParsedExpression() != null
274 					&& !viewingPermission.getParsedExpression().evaluate(user)) {
275 				continue;
276 			}
277 			// If a tools requisites is unset it will be treated as available to
278 			// any, same as Tool.ANY.
279 			if ((tool.getRequisites() & myState) == myState
280 					|| (tool.getRequisites() == Tool.UNDEFINED_REQUISITES)) {
281 				userTools.add(homeTool);
282 			} else {
283 				// LOG.info("--- HIDE TOOL: " + tool.getAlias());
284 			}
285 
286 		}
287 
288 		return userTools;
289 	}
290 
291 	public Properties getKmeProperties() {
292 		return kmeProperties;
293 	}
294 
295 	public void setKmeProperties(Properties kmeProperties) {
296 		this.kmeProperties = kmeProperties;
297 	}
298 
299 	public AdminService getAdminService() {
300 		return adminService;
301 	}
302 
303 	public void setAdminService(AdminService adminService) {
304 		this.adminService = adminService;
305 	}
306 
307 }