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.tours.controllers;
17  
18  import java.io.ByteArrayOutputStream;
19  import java.io.IOException;
20  import java.io.OutputStream;
21  import java.io.UnsupportedEncodingException;
22  import java.net.URLEncoder;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Set;
31  
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  
35  import net.sf.json.JSONArray;
36  import net.sf.json.JSONObject;
37  import net.sf.json.JSONSerializer;
38  import net.sf.json.JsonConfig;
39  
40  import org.apache.commons.lang.StringEscapeUtils;
41  import org.kuali.mobility.security.user.api.User;
42  import org.kuali.mobility.shared.Constants;
43  import org.kuali.mobility.tours.entity.POI;
44  import org.kuali.mobility.tours.entity.POIEmailAddress;
45  import org.kuali.mobility.tours.entity.POIPermission;
46  import org.kuali.mobility.tours.entity.POIPhoneNumber;
47  import org.kuali.mobility.tours.entity.Tour;
48  import org.kuali.mobility.tours.entity.TourPermission;
49  import org.kuali.mobility.tours.service.ToursService;
50  import org.springframework.beans.factory.annotation.Autowired;
51  import org.springframework.stereotype.Controller;
52  import org.springframework.ui.Model;
53  import org.springframework.web.bind.annotation.PathVariable;
54  import org.springframework.web.bind.annotation.RequestMapping;
55  import org.springframework.web.bind.annotation.RequestMethod;
56  import org.springframework.web.bind.annotation.RequestParam;
57  import org.springframework.web.bind.annotation.ResponseBody;
58  
59  import de.micromata.opengis.kml.v_2_2_0.Kml;
60  
61  @Controller
62  @RequestMapping("/tours")
63  public class ToursController {
64  
65  	private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ToursController.class);
66  
67  	@Autowired
68      private ToursService toursService;
69  
70  	//@Autowired
71  	//private AdsService adsService;
72  
73      @RequestMapping(method = RequestMethod.GET)
74      public String index(HttpServletRequest request, Model uiModel) {
75      	List<Tour> tours = toursService.findAllTours();
76      	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
77      	for (Iterator<Tour> iter = tours.iterator(); iter.hasNext(); ){
78      		Tour tour = iter.next();
79      		if (!toursService.hasAccessToViewTour(user, tour)) {
80      			iter.remove();
81      		}
82      	}
83  
84      	uiModel.addAttribute("tours", tours);
85      	return "tours/home";
86      }
87  
88      @RequestMapping(value = "publish", method = RequestMethod.GET)
89      public String publish(HttpServletRequest request, Model uiModel) {
90      	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
91      	if (!toursService.hasAccessToPublish(user)) {
92  			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
93      		return "tours/message";
94  		}
95  
96      	List<Tour> tours = toursService.findAllTours();
97      	List<POI> POIs = toursService.findAllCommonPOI();
98      	for (Iterator<Tour> iter = tours.iterator(); iter.hasNext(); ){
99      		Tour tour = iter.next();
100     		if (!toursService.hasAccessToEditTour(user, tour)) {
101     			iter.remove();
102     		}
103     	}
104     	for (Iterator<POI> iter = POIs.iterator(); iter.hasNext(); ){
105     		POI poi = iter.next();
106     		if (!toursService.hasAccessToEditPOI(user, poi)) {
107     			iter.remove();
108     		}
109     	}
110 
111 
112     	uiModel.addAttribute("tours", tours);
113     	uiModel.addAttribute("pois", POIs);
114     	return "tours/index";
115     }
116 
117 	@RequestMapping(value = "/view/{tourId}", method = RequestMethod.GET)
118     public String viewTour(HttpServletRequest request, Model uiModel, @PathVariable("tourId") long tourId) {
119     	try {
120     		User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
121 	    	Tour tour = toursService.findTourById(tourId);
122 
123 	    	if (!toursService.hasAccessToViewTour(user, tour)){
124 	    		uiModel.addAttribute("message", "You do not have access to view this tour.");
125 	    		return "tours/message";
126 	    	}
127 
128 	    	if (tour != null){
129 	    		if (tour.getPointsOfInterest() != null) {
130 	    			Collections.sort(tour.getPointsOfInterest());
131 	    		}
132 		    	try {
133 		    		if (tour.getFbText1() != null) tour.setFbText1(URLEncoder.encode(tour.getFbText1(), "UTF-8"));
134 		    		if (tour.getFbText2() != null) tour.setFbText2(URLEncoder.encode(tour.getFbText2(), "UTF-8"));
135 				} catch (Exception e) {
136 
137 				}
138 		    	uiModel.addAttribute("tour", tour);
139 		    	try {
140 					uiModel.addAttribute("pageUrl", URLEncoder.encode(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/tours/view/" + tour.getTourId(), "UTF-8"));
141 				} catch (UnsupportedEncodingException e) {
142 				}
143 	    	}
144     	} catch (Exception e) {
145     		LOG.error("Error retrieving tour." + tourId, e);
146     	}
147     	return "tours/tour";
148     }
149 
150 	@RequestMapping(value = "/details/{poiId}", method = RequestMethod.GET)
151     public String viewPoiDetails(HttpServletRequest request, Model uiModel, @PathVariable("poiId") long poiId) {
152     	try {
153 			POI poi = toursService.findPoiById(poiId);
154 
155 			if (poi != null && poi.getTourId() != null) {
156 				User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
157 		    	Tour tour = toursService.findTourById(poi.getTourId());
158 
159 		    	if (!toursService.hasAccessToViewTour(user, tour)){
160 		    		uiModel.addAttribute("message", "You do not have access to view details of this location.");
161 		    		return "tours/message";
162 		    	}
163 
164 		    	POI prevPoi = toursService.findPoiByOrder(poi.getTourId(), poi.getOrder() - 1);
165 		    	POI nextPoi = toursService.findPoiByOrder(poi.getTourId(), poi.getOrder() + 1);
166 
167 		    	if (prevPoi != null) {
168 		    		uiModel.addAttribute("prevPoi", prevPoi);
169 		    	}
170 		    	if (nextPoi != null) {
171 		    		uiModel.addAttribute("nextPoi", nextPoi);
172 		    	}
173 			}
174 
175 	    	if (poi != null && poi.getMedia() != null) {
176 	    		poi.setMedia(StringEscapeUtils.escapeJavaScript(poi.getMedia()));
177 	    	}
178 
179 	    	if (poi.getPhoneNumbers() != null) {
180 	    		for (POIPhoneNumber number : poi.getPhoneNumbers()){
181 	    			number.setFormattedNumber(String.format("(%s) %s-%s", number.getNumber().substring(0, 3), number.getNumber().substring(3, 6), number.getNumber().substring(6, 10)));
182 	    		}
183 	    	}
184 
185 	    	uiModel.addAttribute("poi", poi);
186 		} catch (Exception e) {
187 			LOG.error("Error retrieving POI details." + poiId, e);
188 		}
189     	return "tours/details";
190     }
191 
192     @SuppressWarnings("unchecked")
193 	@RequestMapping(value = "/map/{tourId}", method = RequestMethod.GET)
194     public String viewTourMap(HttpServletRequest request, Model uiModel, @PathVariable("tourId") long tourId) {
195     	try {
196     		User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
197     		Tour tour = toursService.findTourById(tourId);
198 
199 	    	if (!toursService.hasAccessToViewTour(user, tour)){
200 	    		uiModel.addAttribute("message", "You do not have access to view this tour.");
201 	    		return "tours/message";
202 	    	}
203 
204 	    	uiModel.addAttribute("tour", tour);
205 
206 	    	JsonConfig config = new JsonConfig();
207 	    	config.registerPropertyExclusion(POI.class, "tour");
208 	    	config.registerPropertyExclusion(POI.class, "versionNumber");
209 	    	config.registerPropertyExclusion(POI.class, "tourId");
210 	    	config.registerPropertyExclusion(POI.class, "permissions");
211 	    	config.registerPropertyExclusion(POI.class, "phoneNumbers");
212 	    	config.registerPropertyExclusion(Tour.class, "permissions");
213 	    	JSONObject json =  (JSONObject) JSONSerializer.toJSON(tour, config);
214 	    	JSONArray pointsOfInterest = json.getJSONArray("pointsOfInterest");
215 	    	for (Iterator<JSONObject> iter = pointsOfInterest.iterator(); iter.hasNext();) {
216 	    		try {
217 	    			JSONObject poi = iter.next();
218 	    			String mediaJson = poi.getString("media");
219 	    			if (!mediaJson.isEmpty()) {
220 		    			JSONArray media = (JSONArray) JSONSerializer.toJSON(mediaJson);
221 						poi.element("media", media);
222 	    			} else {
223 	    				poi.element("media", new JSONArray());
224 	    			}
225 				} catch (Exception e) {}
226 	    	}
227 	    	uiModel.addAttribute("tourJson", json.toString());
228     	} catch (Exception e) {
229     		LOG.error("Error viewing map for tour " + tourId, e);
230     	}
231     	return "tours/map";
232     }
233 
234     @SuppressWarnings("unchecked")
235 	@RequestMapping(value = "new", method = RequestMethod.GET)
236     public String edit(HttpServletRequest request, Model uiModel) {
237     	try {
238     		User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
239         	if (!toursService.hasAccessToPublish(user)) {
240     			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
241         		return "tours/message";
242     		}
243 	    	List<POI> definedPois = toursService.findAllCommonPOI();
244 	    	for (Iterator<POI> iter = definedPois.iterator(); iter.hasNext(); ){
245 	    		POI poi = iter.next();
246 	    		if (!toursService.hasAccessToViewPOI(user, poi)) {
247 	    			iter.remove();
248 	    		}
249 	    	}
250 	    	JsonConfig config = new JsonConfig();
251 	    	config.registerPropertyExclusion(POI.class, "tour");
252 	    	config.registerPropertyExclusion(POI.class, "versionNumber");
253 	    	config.registerPropertyExclusion(POI.class, "tourId");
254 	    	config.registerPropertyExclusion(POI.class, "permissions");
255 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "poi");
256 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "poiId");
257 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "id");
258 	    	config.registerPropertyExclusion(TourPermission.class, "tour");
259 	    	config.registerPropertyExclusion(TourPermission.class, "tourId");
260 	    	config.registerPropertyExclusion(TourPermission.class, "permissionId");
261 	    	JSONArray pointsOfInterest =  (JSONArray) JSONSerializer.toJSON(definedPois, config);
262 	    	for (Iterator<JSONObject> iter = pointsOfInterest.iterator(); iter.hasNext();) {
263 	    		try {
264 	    			JSONObject poi = iter.next();
265 	    			String mediaJson = poi.getString("media");
266 	    			if (!mediaJson.isEmpty()) {
267 		    			JSONArray media = (JSONArray) JSONSerializer.toJSON(mediaJson);
268 						poi.element("media", media);
269 	    			} else {
270 	    				poi.element("media", new JSONArray());
271 	    			}
272 				} catch (Exception e) {}
273 	    	}
274 	    	uiModel.addAttribute("pois", pointsOfInterest.toString());
275     	} catch (Exception e) {
276     		LOG.error("Error creating new tour.", e);
277     	}
278     	return "tours/edit";
279     }
280 
281     @SuppressWarnings("unchecked")
282 	@RequestMapping(value = "/edit/{tourId}", method = RequestMethod.GET)
283     public String editTour(Model uiModel, HttpServletRequest request, @PathVariable("tourId") long tourId) {
284     	try {
285     		User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
286         	if (!toursService.hasAccessToPublish(user)) {
287     			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
288         		return "tours/message";
289     		}
290     		Tour tour = toursService.findTourById(tourId);
291 
292 	    	if (!toursService.hasAccessToEditTour(user, tour)){
293 	    		uiModel.addAttribute("message", "You do not have access to edit this tour.");
294 	    		return "tours/message";
295 	    	}
296 
297 	    	if (tour.getPointsOfInterest() != null) {
298 	    		Collections.sort(tour.getPointsOfInterest());
299 	    	}
300 	    	JsonConfig config = new JsonConfig();
301 	    	config.registerPropertyExclusion(POI.class, "tour");
302 	    	config.registerPropertyExclusion(POI.class, "versionNumber");
303 	    	config.registerPropertyExclusion(POI.class, "tourId");
304 	    	config.registerPropertyExclusion(POI.class, "permissions");
305 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "poi");
306 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "poiId");
307 	    	config.registerPropertyExclusion(POIPhoneNumber.class, "id");
308 	    	config.registerPropertyExclusion(POIEmailAddress.class, "poi");
309 	    	config.registerPropertyExclusion(POIEmailAddress.class, "poiId");
310 	    	config.registerPropertyExclusion(POIEmailAddress.class, "id");
311 	    	config.registerPropertyExclusion(TourPermission.class, "tour");
312 	    	config.registerPropertyExclusion(TourPermission.class, "tourId");
313 	    	config.registerPropertyExclusion(TourPermission.class, "permissionId");
314 	    	JSONObject json =  (JSONObject) JSONSerializer.toJSON(tour, config);
315 	    	JSONArray pointsOfInterest = json.getJSONArray("pointsOfInterest");
316 	    	if (pointsOfInterest != null) {
317 		    	for (Iterator<JSONObject> iter = pointsOfInterest.iterator(); iter.hasNext();) {
318 		    		try {
319 		    			JSONObject poi = iter.next();
320 		    			String mediaJson = poi.getString("media");
321 		    			if (!mediaJson.isEmpty()) {
322 			    			JSONArray media = (JSONArray) JSONSerializer.toJSON(mediaJson);
323 							poi.element("media", media);
324 		    			} else {
325 		    				poi.element("media", new JSONArray());
326 		    			}
327 					} catch (Exception e) {
328 						LOG.error("Problem modifying media collection for tour POI", e);
329 					}
330 		    	}
331 	    	}
332 	    	
333 	    	uiModel.addAttribute("tourJson", json.toString());
334 
335 	    	List<POI> definedPois = toursService.findAllCommonPOI();
336 	    	for (Iterator<POI> iter = definedPois.iterator(); iter.hasNext(); ){
337 	    		POI poi = iter.next();
338 	    		if (!toursService.hasAccessToViewPOI(user, poi)) {
339 	    			iter.remove();
340 	    		}
341 	    	}
342 	    	pointsOfInterest =  (JSONArray) JSONSerializer.toJSON(definedPois, config);
343 	    	for (Iterator<JSONObject> iter = pointsOfInterest.iterator(); iter.hasNext();) {
344 	    		try {
345 	    			JSONObject poi = iter.next();
346 	    			String mediaJson = poi.getString("media");
347 	    			if (!mediaJson.isEmpty()) {
348 		    			JSONArray media = (JSONArray) JSONSerializer.toJSON(mediaJson);
349 						poi.element("media", media);
350 	    			} else {
351 	    				poi.element("media", new JSONArray());
352 	    			}
353 				} catch (Exception e) {
354 					LOG.error("Problem modifying media collection for common POI", e);
355 				}
356 	    	}
357 	    	uiModel.addAttribute("pois", pointsOfInterest.toString());
358     	} catch (Exception e) {
359     		LOG.error("Error editing tour " + tourId, e);
360     	}
361     	return "tours/edit";
362     }
363 
364     @RequestMapping(value = "/verify", method = RequestMethod.GET)
365     @ResponseBody
366     public String verifyAdsGroup(@RequestParam("group") String groupName) {
367     	boolean valid = true;//adsService.validateAdsGroup(groupName);
368     	Map<String, Object> result = new HashMap<String, Object>();
369     	result.put("group", groupName);
370     	result.put("valid", valid);
371 
372     	return JSONSerializer.toJSON(result).toString();
373     }
374 
375     @RequestMapping(value = "edit", method = RequestMethod.POST)
376     public String save(HttpServletRequest request, @RequestParam("data") String postData,  Model uiModel) {
377     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
378     	if (!toursService.hasAccessToPublish(user)) {
379 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
380     		return "tours/message";
381 		}
382 
383     	Tour tour = convertTourFromJson(postData);
384 
385     	if (tour.getTourId() != null) {
386     		Tour existingTour = toursService.findTourById(tour.getTourId());
387     		if (existingTour != null && !toursService.hasAccessToEditTour(user, existingTour)){
388         		uiModel.addAttribute("message", "You do not have access to edit this tour.");
389         		return "tours/message";
390         	}
391     	}
392 
393     	toursService.saveTour(tour);
394     	return "redirect:/tours/publish";
395     }
396 
397     @RequestMapping(value = "delete/{tourId}", method = RequestMethod.GET)
398     public String delete(Model uiModel, HttpServletRequest request, @PathVariable("tourId") Long tourId) {
399     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
400     	if (!toursService.hasAccessToPublish(user)) {
401 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
402     		return "tours/message";
403 		}
404     	Tour tour = toursService.findTourById(tourId);
405     	if (!toursService.hasAccessToEditTour(user, tour)){
406     		uiModel.addAttribute("message", "You do not have access to delete this tour.");
407     		return "tours/message";
408     	}
409     	toursService.deleteTourById(tourId);
410     	return "redirect:/tours/publish";
411     }
412 
413     @RequestMapping(value = "copy/{tourId}", method = RequestMethod.GET)
414     public String copy(Model uiModel, HttpServletRequest request, @PathVariable("tourId") Long tourId) {
415     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
416     	if (!toursService.hasAccessToPublish(user)) {
417 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
418     		return "tours/message";
419 		}
420     	Tour tour = toursService.findTourById(tourId);
421     	if (!toursService.hasAccessToEditTour(user, tour)){
422     		uiModel.addAttribute("message", "You do not have access to delete this tour.");
423     		return "tours/message";
424     	}
425     	toursService.duplicateTourById(tourId);
426     	return "redirect:/tours/publish";
427     }
428 
429     @RequestMapping(value = "poi/new", method = RequestMethod.GET)
430     public String editPoi(Model uiModel, HttpServletRequest request) {
431     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
432     	if (!toursService.hasAccessToPublish(user)) {
433 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
434     		return "tours/message";
435 		}
436     	return "tours/editPoi";
437     }
438 
439 	@RequestMapping(value = "poi/edit/{poiId}", method = RequestMethod.GET)
440     public String editPoi(HttpServletRequest request, Model uiModel, @PathVariable("poiId") long poiId) {
441 		User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
442     	if (!toursService.hasAccessToPublish(user)) {
443 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
444     		return "tours/message";
445 		}
446 
447 		POI poi = toursService.findPoiById(poiId);
448     	if (!toursService.hasAccessToEditPOI(user, poi)){
449     		uiModel.addAttribute("message", "You do not have access to edit this point of interest.");
450     		return "tours/message";
451     	}
452 
453     	JsonConfig config = new JsonConfig();
454     	config.registerPropertyExclusion(POI.class, "tour");
455     	config.registerPropertyExclusion(POI.class, "tourId");
456     	config.registerPropertyExclusion(POIPhoneNumber.class, "poi");
457     	config.registerPropertyExclusion(POIPhoneNumber.class, "id");
458     	config.registerPropertyExclusion(POIPhoneNumber.class, "poiId");
459     	config.registerPropertyExclusion(POIEmailAddress.class, "poi");
460     	config.registerPropertyExclusion(POIEmailAddress.class, "poiId");
461     	config.registerPropertyExclusion(POIEmailAddress.class, "id");
462     	config.registerPropertyExclusion(POIPermission.class, "poiId");
463     	config.registerPropertyExclusion(POIPermission.class, "poi");
464     	config.registerPropertyExclusion(POIPermission.class, "permissionId");
465     	JSONObject json =  (JSONObject) JSONSerializer.toJSON(poi, config);
466 		String mediaJson = json.getString("media");
467 		if (!mediaJson.isEmpty()) {
468 			try {
469 				JSONArray media = (JSONArray) JSONSerializer.toJSON(mediaJson);
470 				json.element("media", media);
471 			} catch (Exception e) {
472 				LOG.error("Problem modifying media collection for common POI", e);
473 			}
474 		} else {
475 			json.element("media", new JSONArray());
476 		}
477     	uiModel.addAttribute("poiJson", json.toString());
478     	return "tours/editPoi";
479     }
480 
481     @RequestMapping(value = "poi/edit", method = RequestMethod.POST)
482     public String savePoi(HttpServletRequest request, @RequestParam("data") String postData,  Model uiModel) {
483     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
484     	if (!toursService.hasAccessToPublish(user)) {
485 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
486 			return "tours/message";
487 		}
488 
489     	POI poi = convertPoiFromJson(postData);
490 
491     	if (poi != null && poi.getPoiId() != null) {
492     		POI existingPOI = toursService.findPoiById(poi.getPoiId());
493 
494     		if (!toursService.hasAccessToEditPOI(user, existingPOI)){
495         		uiModel.addAttribute("message", "You do not have access to edit this point of interest.");
496         		return "tours/message";
497         	}
498     	}
499 
500     	toursService.savePoi(poi);
501     	return "redirect:/tours/publish";
502     }
503 
504     @RequestMapping(value = "poi/copy/{poiId}", method = RequestMethod.GET)
505     public String copyPoi(@PathVariable("poiId") Long poiId) {
506     	toursService.duplicatePoiById(poiId);
507     	return "redirect:/tours/publish";
508     }
509 
510     @RequestMapping(value = "poi/delete/{poiId}", method = RequestMethod.GET)
511     public String deletePoi(HttpServletRequest request, @PathVariable("poiId") Long poiId, Model uiModel) {
512     	User user = (User) request.getSession().getAttribute(Constants.KME_USER_KEY);
513     	if (!toursService.hasAccessToPublish(user)) {
514 			uiModel.addAttribute("message", "You do not have access to create or edit tours.");
515     		return "tours/message";
516 		}
517 
518     	POI poi = toursService.findPoiById(poiId);
519     	if (!toursService.hasAccessToEditPOI(user, poi)){
520     		uiModel.addAttribute("message", "You do not have access to delete this point of interest.");
521     		return "tours/message";
522     	}
523 
524     	toursService.deletePoiById(poiId);
525     	return "redirect:/tours/publish";
526     }
527 
528     @RequestMapping(value = "kml/{tourId}", method = RequestMethod.GET)
529     public String downloadKml(@PathVariable("tourId") Long tourId, HttpServletResponse response) {
530     	Tour tour = toursService.findTourById(tourId);
531     	Kml kml = toursService.createTourKml(tour);
532     	OutputStream os = new ByteArrayOutputStream();
533     	try {
534 			kml.marshal(os);
535 		} catch (Exception e) {
536 		}
537     	byte [] data = os.toString().getBytes();
538     	response.setContentType("application/vnd.google-earth.kml+xml");
539 		response.setContentLength(data.length);
540 		response.setHeader("Content-Disposition", "attachment; filename=\"" + tour.getName() + ".kml\"" );
541 		try {
542 			response.getOutputStream().write(data, 0, data.length);
543 		} catch (IOException e) {
544 		}
545     	return null;
546     }
547 
548     @RequestMapping(value = "kml", method = RequestMethod.POST)
549     public String downloadKml(@RequestParam("data") String postData, @RequestParam("name") String name, HttpServletResponse response) {
550     	String newline = System.getProperty("line.separator");
551     	byte [] data = postData.replace("<EOL>", newline).getBytes();
552     	response.setContentType("application/vnd.google-earth.kml+xml");
553 		response.setContentLength(data.length);
554 		response.setHeader("Content-Disposition", "attachment; filename=\"" + name + ".kml\"" );
555 		try {
556 			response.getOutputStream().write(data, 0, data.length);
557 		} catch (IOException e) {
558 		}
559     	return null;
560     }
561 
562     @SuppressWarnings("unchecked")
563 	private Tour convertTourFromJson(String json) {
564     	Tour tour = new Tour();
565     	JSONObject tourJson = (JSONObject) JSONSerializer.toJSON(json);
566 
567     	try {
568     		tour.setTourId(tourJson.getLong("id"));
569     	} catch (Exception e) {
570     		tour.setTourId(null);
571     	}
572     	tour.setName(tourJson.getString("name"));
573     	tour.setDescription(tourJson.getString("description"));
574     	tour.setImageUrl(tourJson.getString("imageUrl"));
575     	tour.setPath(tourJson.getString("path"));
576 
577     	tour.setTweetText1(tourJson.getString("tweetText1"));
578     	tour.setTweetText2(tourJson.getString("tweetText2"));
579     	tour.setFbText1(tourJson.getString("fbText1"));
580     	tour.setFbText2(tourJson.getString("fbText2"));
581 
582     	tour.setTweetText1Enabled(tourJson.getBoolean("tweetText1Enabled") ? "T" : "F");
583     	tour.setTweetText2Enabled(tourJson.getBoolean("tweetText2Enabled") ? "T" : "F");
584     	tour.setFbText1Enabled(tourJson.getBoolean("fbText1Enabled") ? "T" : "F");
585     	tour.setFbText2Enabled(tourJson.getBoolean("fbText2Enabled") ? "T" : "F");
586 
587     	try {
588     		tour.setVersionNumber(tourJson.getLong("version"));
589     	} catch (Exception e) {
590     		tour.setVersionNumber(null);
591     	}
592     	try {
593     		tour.setDistance(tourJson.getLong("distance"));
594     	} catch (Exception e) {
595     		tour.setDistance(null);
596     	}
597 
598     	JSONArray permissionsArray = tourJson.getJSONArray("permissions");
599 		Set<TourPermission> permissions = new HashSet<TourPermission>();
600 		for (Iterator<JSONObject> iter = permissionsArray.iterator(); iter.hasNext();) {
601 			try {
602 				JSONObject permission = iter.next();
603 				TourPermission tourPermission = new TourPermission();
604 
605 				tourPermission.setGroupName(permission.getString("group"));
606 				tourPermission.setType(permission.getString("type"));
607 				tourPermission.setTour(tour);
608 				tourPermission.setTourId(tour.getTourId());
609 
610 				permissions.add(tourPermission);
611 			} catch (Exception e) {
612 				LOG.error("Error parsing tour permission.", e);
613 			}
614 		}
615 		tour.setPermissions(permissions);
616 
617     	JSONArray pointsOfInterest = tourJson.getJSONArray("POIs");
618 		List<POI> POIs = new ArrayList<POI>();
619 		for (Iterator<JSONObject> iter = pointsOfInterest.iterator(); iter.hasNext();) {
620 			JSONObject pointOfInterest = iter.next();
621 			POI poi = new POI();
622 
623 			try {
624 				poi.setPoiId(pointOfInterest.getLong("poiId"));
625 	    	} catch (Exception e) {
626 	    		poi.setPoiId(null);
627 	    	}
628 			try {
629 				poi.setName(pointOfInterest.getString("name"));
630 	    	} catch (Exception e) {
631 	    		poi.setName(null);
632 	    	}
633 			try {
634 				poi.setOfficialName(pointOfInterest.getString("officialName"));
635 	    	} catch (Exception e) {
636 	    		poi.setOfficialName(null);
637 	    	}
638 			try {
639 				poi.setDescription(pointOfInterest.getString("description"));
640 	    	} catch (Exception e) {
641 	    		poi.setDescription(null);
642 	    	}
643 			try {
644 				poi.setShortDescription(pointOfInterest.getString("shortDescription"));
645 	    	} catch (Exception e) {
646 	    		poi.setShortDescription(null);
647 	    	}
648 			try {
649 				poi.setLocationId(pointOfInterest.getString("iuBuildingCode"));
650 	    	} catch (Exception e) {
651 	    		try {
652 					poi.setLocationId(pointOfInterest.getString("venueId"));
653 		    	} catch (Exception ex) {
654 		    		poi.setLocationId(null);
655 		    	}
656 	    	}
657 			poi.setType(pointOfInterest.getString("type"));
658 
659 			try {
660 				poi.setDistanceToNextPoi(pointOfInterest.getLong("distanceToNext"));
661 	    	} catch (Exception e) {
662 	    		poi.setDistanceToNextPoi(null);
663 	    	}
664 
665 			poi.setOrder(pointOfInterest.getInt("order"));
666 
667 			JSONObject location = pointOfInterest.getJSONObject("location");
668 			poi.setLatitude(((Double)location.getDouble("lat")).floatValue());
669 			poi.setLongitude(((Double)location.getDouble("lng")).floatValue());
670 			try {
671 				poi.setMedia(pointOfInterest.getString("media"));
672 			} catch (Exception e) {}
673 			try {
674 				poi.setUrl(pointOfInterest.getString("url"));
675 			} catch (Exception e) {}
676 			try {
677 				poi.setThumbnailUrl(pointOfInterest.getString("thumbnailUrl"));
678 	    	} catch (Exception e) {
679 	    		poi.setThumbnailUrl(null);
680 	    	}
681 			try {
682 				poi.setFbLikeUrl(pointOfInterest.getString("fbLikeUrl"));
683 	    	} catch (Exception e) {
684 	    		poi.setFbLikeUrl(null);
685 	    	}
686 			try {
687 				poi.setFbLikeButtonEnabled(pointOfInterest.getBoolean("fbLikeButtonEnabled") ? "T" : "F");
688 	    	} catch (Exception e) {
689 	    		poi.setFbLikeButtonEnabled("F");
690 	    	}
691 
692 			JSONArray phoneNumbers = pointOfInterest.getJSONArray("phoneNumbers");
693 			if (phoneNumbers != null) {
694 				for (Iterator<JSONObject> iter2 = phoneNumbers.iterator(); iter2.hasNext();) {
695 					JSONObject phnNumber = iter2.next();
696 					POIPhoneNumber phoneNumber = new POIPhoneNumber();
697 					try {
698 						phoneNumber.setName(phnNumber.getString("name"));
699 			    	} catch (Exception e) {
700 			    		phoneNumber.setName(null);
701 			    	}
702 					try {
703 						phoneNumber.setNumber(phnNumber.getString("value"));
704 			    	} catch (Exception e) {
705 			    		phoneNumber.setNumber(null);
706 			    	}
707 					phoneNumber.setPoi(poi);
708 					phoneNumber.setPoiId(poi.getPoiId());
709 					poi.getPhoneNumbers().add(phoneNumber);
710 				}
711 			}
712 
713 			JSONArray emailAddresses = pointOfInterest.getJSONArray("emailAddresses");
714 			if (emailAddresses != null) {
715 				for (Iterator<JSONObject> iter2 = emailAddresses.iterator(); iter2.hasNext();) {
716 					JSONObject email = iter2.next();
717 					POIEmailAddress emailAddress = new POIEmailAddress();
718 					try {
719 						emailAddress.setName(email.getString("name"));
720 			    	} catch (Exception e) {
721 			    		emailAddress.setName(null);
722 			    	}
723 					try {
724 						emailAddress.setAddress(email.getString("address"));
725 			    	} catch (Exception e) {
726 			    		emailAddress.setAddress(null);
727 			    	}
728 					emailAddress.setPoi(poi);
729 					emailAddress.setPoiId(poi.getPoiId());
730 					poi.getEmailAddresses().add(emailAddress);
731 				}
732 			}
733 
734 			poi.setTourId(tour.getTourId());
735 			poi.setTour(tour);
736 			POIs.add(poi);
737 		}
738     	tour.setPointsOfInterest(POIs);
739 
740     	return tour;
741     }
742 
743 	@SuppressWarnings("unchecked")
744 	private POI convertPoiFromJson(String json) {
745     	POI poi = new POI();
746     	JSONObject pointOfInterest = (JSONObject) JSONSerializer.toJSON(json);
747 
748 		try {
749 			poi.setPoiId(pointOfInterest.getLong("id"));
750     	} catch (Exception e) {
751     		poi.setPoiId(null);
752     	}
753 		try {
754 			poi.setVersionNumber(pointOfInterest.getLong("version"));
755     	} catch (Exception e) {
756     		poi.setVersionNumber(null);
757     	}
758 
759 		try {
760 			poi.setName(pointOfInterest.getString("name"));
761     	} catch (Exception e) {
762     		poi.setName(null);
763     	}
764 		try {
765 			poi.setOfficialName(pointOfInterest.getString("officialName"));
766     	} catch (Exception e) {
767     		poi.setOfficialName(null);
768     	}
769 		try {
770 			poi.setDescription(pointOfInterest.getString("description"));
771     	} catch (Exception e) {
772     		poi.setDescription(null);
773     	}
774 		try {
775 			poi.setShortDescription(pointOfInterest.getString("shortDescription"));
776     	} catch (Exception e) {
777     		poi.setShortDescription(null);
778     	}
779 		try {
780 			poi.setLocationId(pointOfInterest.getString("locationId"));
781     	} catch (Exception e) {
782     		poi.setLocationId(null);
783     	}
784 		try {
785 			poi.setUrl(pointOfInterest.getString("url"));
786     	} catch (Exception e) {
787     		poi.setUrl(null);
788     	}
789 		try {
790 			poi.setThumbnailUrl(pointOfInterest.getString("thumbnailUrl"));
791     	} catch (Exception e) {
792     		poi.setThumbnailUrl(null);
793     	}
794 		try {
795 			poi.setFbLikeUrl(pointOfInterest.getString("fbLikeUrl"));
796     	} catch (Exception e) {
797     		poi.setFbLikeUrl(null);
798     	}
799 		poi.setFbLikeButtonEnabled(pointOfInterest.getBoolean("fbLikeButtonEnabled") ? "T" : "F");
800 		poi.setType(pointOfInterest.getString("type"));
801 
802 		JSONArray permissionsArray = pointOfInterest.getJSONArray("permissions");
803 		Set<POIPermission> permissions = new HashSet<POIPermission>();
804 		for (Iterator<JSONObject> iter = permissionsArray.iterator(); iter.hasNext();) {
805 			try {
806 				JSONObject permission = iter.next();
807 				POIPermission poiPermission = new POIPermission();
808 
809 				poiPermission.setGroupName(permission.getString("group"));
810 				poiPermission.setType(permission.getString("type"));
811 				poiPermission.setPoi(poi);
812 				poiPermission.setPoiId(poi.getPoiId());
813 
814 				permissions.add(poiPermission);
815 			} catch (Exception e) {
816 				LOG.error("Error parsing tour permission.", e);
817 			}
818 		}
819 		poi.setPermissions(permissions);
820 
821 		JSONArray phoneNumbers = pointOfInterest.getJSONArray("phoneNumbers");
822 		if (phoneNumbers != null) {
823 			for (Iterator<JSONObject> iter2 = phoneNumbers.iterator(); iter2.hasNext();) {
824 				JSONObject phnNumber = iter2.next();
825 				POIPhoneNumber phoneNumber = new POIPhoneNumber();
826 				try {
827 					phoneNumber.setName(phnNumber.getString("name"));
828 		    	} catch (Exception e) {
829 		    		phoneNumber.setName(null);
830 		    	}
831 				try {
832 					phoneNumber.setNumber(phnNumber.getString("value"));
833 		    	} catch (Exception e) {
834 		    		phoneNumber.setNumber(null);
835 		    	}
836 				phoneNumber.setPoi(poi);
837 				phoneNumber.setPoiId(poi.getPoiId());
838 				poi.getPhoneNumbers().add(phoneNumber);
839 			}
840 		}
841 		JSONArray emailAddresses = pointOfInterest.getJSONArray("emailAddresses");
842 		if (emailAddresses != null) {
843 			for (Iterator<JSONObject> iter2 = emailAddresses.iterator(); iter2.hasNext();) {
844 				JSONObject email = iter2.next();
845 				POIEmailAddress emailAddress = new POIEmailAddress();
846 				try {
847 					emailAddress.setName(email.getString("name"));
848 		    	} catch (Exception e) {
849 		    		emailAddress.setName(null);
850 		    	}
851 				try {
852 					emailAddress.setAddress(email.getString("address"));
853 		    	} catch (Exception e) {
854 		    		emailAddress.setAddress(null);
855 		    	}
856 				emailAddress.setPoi(poi);
857 				emailAddress.setPoiId(poi.getPoiId());
858 				poi.getEmailAddresses().add(emailAddress);
859 			}
860 		}
861 
862 		poi.setTour(null);
863 		poi.setTourId(null);
864 
865 		JSONObject location = pointOfInterest.getJSONObject("location");
866 		poi.setLatitude(((Double)location.getDouble("latitude")).floatValue());
867 		poi.setLongitude(((Double)location.getDouble("longitude")).floatValue());
868 		try {
869 			poi.setMedia(pointOfInterest.getString("media"));
870 		} catch (Exception e) {}
871 
872     	return poi;
873     }
874 
875 	public ToursService getToursService() {
876 		return toursService;
877 	}
878 	
879 	public void setToursService(ToursService toursService) {
880 		this.toursService = toursService;
881 	}
882 }