View Javadoc
1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.webapp.action;
24  
25  import java.util.List;
26  
27  import javax.servlet.http.HttpServletRequest;
28  
29  import org.apache.struts2.ServletActionContext;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.springframework.beans.factory.annotation.Required;
33  import org.springframework.transaction.PlatformTransactionManager;
34  import org.springframework.transaction.TransactionDefinition;
35  import org.springframework.transaction.TransactionStatus;
36  import org.springframework.transaction.support.DefaultTransactionDefinition;
37  
38  import com.gisgraphy.domain.geoloc.entity.Country;
39  import com.gisgraphy.domain.geoloc.entity.OpenStreetMap;
40  import com.gisgraphy.domain.repository.CountryDao;
41  import com.gisgraphy.domain.repository.IIdGenerator;
42  import com.gisgraphy.domain.repository.IOpenStreetMapDao;
43  import com.gisgraphy.domain.repository.ISolRSynchroniser;
44  import com.gisgraphy.helper.GeolocHelper;
45  import com.gisgraphy.helper.StringHelper;
46  import com.gisgraphy.service.IInternationalisationService;
47  import com.gisgraphy.street.StreetType;
48  import com.opensymphony.xwork2.ActionContext;
49  import com.opensymphony.xwork2.Preparable;
50  import com.vividsolutions.jts.geom.LineString;
51  import com.vividsolutions.jts.geom.Point;
52  
53  /**
54   * Edit Street (openstreetMap entity) action
55   * 
56   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
57   */
58  
59  public class EditStreetAction extends BaseAction implements Preparable {
60  
61  	private static final long serialVersionUID = 4785676484073350068L;
62  
63  	private static Logger logger = LoggerFactory
64  			.getLogger(EditStreetAction.class);
65  
66  	private IOpenStreetMapDao openStreetMapDao;
67  
68  
69  	private OpenStreetMap openstreetmap;
70  
71  	private IInternationalisationService internationalisationService;
72  
73  	private CountryDao countryDao;
74  	
75  	private IIdGenerator IdGenerator;
76  	/**
77  	 * The transaction manager
78  	 */
79  	private PlatformTransactionManager transactionManager;
80  
81  	private TransactionStatus txStatus = null;
82  
83  	private DefaultTransactionDefinition txDefinition;
84  	
85  	private ISolRSynchroniser solRSynchroniser;
86  
87  
88  	/*
89  	 * Those specific fields needs to be process separately because of decimal
90  	 * separator or enum type
91  	 */
92  	private String latitude;
93  	private String longitude;
94  	private Float latitudeAsFloat = null;
95  	private Float longitudeAsFloat = null;
96  	private String streettype;
97  	private Long id;
98  	
99  	private String errorMessage;
100 	private String stackTrace;
101 
102 	public String getStreettype() {
103 		return streettype;
104 	}
105 
106 	public void setStreettype(String streettype) {
107 		this.streettype = streettype;
108 	}
109 
110 	private String shape;
111 
112 	/**
113 	 * @return the available countries
114 	 */
115 	public List<Country> getCountries() {
116 		return countryDao.getAllSortedByName();
117 	}
118 
119 	public StreetType[] getStreetTypes() {
120 		return StreetType.values();
121 	}
122 
123 	public void prepare() {
124 		// we have to test httpparameter because prepare is called before the
125 		// setters are called
126 		HttpServletRequest request = (HttpServletRequest) ActionContext
127 				.getContext().get(ServletActionContext.HTTP_REQUEST);
128 		String parameter = request.getParameter("gid");
129 		if (parameter != null && !parameter.equals("")) {
130 			Long idAsLong = null;
131 			try {
132 			    idAsLong = Long.parseLong(parameter);
133 			} catch (NumberFormatException e) {
134 			    errorMessage="gid should be numeric";
135 				logger.error(errorMessage);
136 			}
137 			id = idAsLong;
138 		}
139 		if (openstreetmap != null && openstreetmap.getId() != null) {
140 			openstreetmap = openStreetMapDao.get(openstreetmap.getId());
141 		} else if (id != null) {
142 			openstreetmap = openStreetMapDao.getByGid(getId());
143 		}
144 	}
145 
146 	public String input() {
147 		return INPUT;
148 	}
149 
150 	public String save() {
151 		return doSave();
152 	}
153 
154 	public String doSave() {
155 		if (openstreetmap != null) {
156 			checkMissingRequiredfields();
157 			//we sync the idgenerator in case an import is in progress
158 			//or several person add street simultaneously
159 			IdGenerator.sync();
160 			if(openstreetmap.getGid()==null){
161 			    openstreetmap.setGid(generateGid());
162 			}
163 			openstreetmap.setLocation(processPoint());
164 			LineString shapeProcessed = processShape();
165 			openstreetmap.setShape(shapeProcessed);
166 			openstreetmap.setStreetType(processStreettype());
167 			openstreetmap.setLength(processLength(shapeProcessed));
168 			if (getFieldErrors().keySet().size() > 0) {
169 				return INPUT;
170 			} else {
171 				startTransaction();
172 				try {
173 				    	StringHelper.updateOpenStreetMapEntityForIndexation(openstreetmap);
174 					openStreetMapDao.save(openstreetmap);
175 					
176 				} catch (Exception e) {
177 					rollbackTransaction();
178 					errorMessage="could not save street " + e.getMessage();
179 					stackTrace= StringHelper.getStackTraceAsString(e);
180 					logger.error(errorMessage, e);
181 					return ERROR;
182 				}
183 				commitTransaction();
184 				return SUCCESS;
185 			}
186 		} else {
187 			errorMessage="There is no street to save";
188 			logger.error(errorMessage);
189 			return ERROR;
190 		}
191 	}
192 
193 	private void checkMissingRequiredfields() {
194 		if (getLatitude()==null){
195 			addFieldError("latitude",internationalisationService.getString("errors.required", new String[]{"latitude"}) );
196 		}
197 		if (getLongitude()==null){
198 			addFieldError("longitude",internationalisationService.getString("errors.required", new String[]{"longitude"}) );
199 		}
200 		if (openstreetmap!=null && (openstreetmap.getCountryCode()==null || openstreetmap.getCountryCode().trim().equals(""))){
201 			addFieldError("country",internationalisationService.getString("errors.required", new String[]{"country"}) );
202 		}
203 		
204 	}
205 
206 	protected Double processLength(LineString lineString) {
207 		Double lengthAsDouble = null;
208 		if (lineString != null) {
209 			lengthAsDouble = lineString.getLength();
210 		}
211 		return lengthAsDouble;
212 	}
213 
214 	private void commitTransaction() {
215 		transactionManager.commit(txStatus);
216 		solRSynchroniser.commit();
217 	}
218 
219 	private void rollbackTransaction() {
220 		transactionManager.rollback(txStatus);
221 	}
222 
223 	private void startTransaction() {
224 		txDefinition = new DefaultTransactionDefinition();
225 		txDefinition
226 				.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
227 		txDefinition.setReadOnly(false);
228 
229 		txStatus = transactionManager.getTransaction(txDefinition);
230 	}
231 
232 	protected StreetType processStreettype() {
233 		if (getStreettype() != null) {
234 			StreetType type;
235 			try {
236 				type = StreetType.valueOf(getStreettype());
237 				return type;
238 			} catch (Exception e) {
239 				logger.warn("can not determine streetType for "
240 						+ getStreettype() + " : " + e);
241 			}
242 		}
243 		return null;
244 	}
245 
246 	protected LineString processShape() {
247 		LineString lineString;
248 		if ((shape == null || "".equals(shape)) && latitudeAsFloat != null && longitudeAsFloat != null) {
249 			try {
250 				lineString = GeolocHelper.createLineString("LINESTRING ("
251 						+ longitudeAsFloat + " " + latitudeAsFloat + "," + longitudeAsFloat + " "
252 						+ latitudeAsFloat + ")");
253 			} catch (Exception e) {
254 				logger.warn("can not createlinestring with lat/long "
255 						+ latitudeAsFloat + "/" + longitudeAsFloat);
256 				addFieldError(
257 						"shape",
258 						internationalisationService
259 								.getString("error.wrong.lat.long.for.linestring"));
260 				return null;
261 			}
262 		} else {
263 			try {
264 				lineString = GeolocHelper.createLineString(shape);
265 			} catch (Exception e) {
266 				logger.warn("Can not determine shape for " + shape);
267 				addFieldError("shape",
268 						internationalisationService
269 								.getString("errors.invalid",new String[]{"shape"}));
270 				return null;
271 			}
272 		}
273 		return lineString;
274 	}
275 
276 	protected Point processPoint() {
277 		try {
278 			if (latitude != null) {
279 				try {
280 					latitudeAsFloat = GeolocHelper
281 							.parseInternationalDouble(latitude);
282 					if (latitudeAsFloat < -90 || latitudeAsFloat > 90) {
283 						addFieldError("latitude",
284 								internationalisationService
285 										.getString("error.latitude.outOfRange"));
286 					}
287 				} catch (Exception e) {
288 					logger.warn("latitude : " + latitude + "is not a number");
289 					addFieldError("latitude",
290 							internationalisationService.getString(
291 									"error.notANumber",
292 									new String[] { "latitude" }));
293 				}
294 
295 			}
296 			if (longitude != null) {
297 				try {
298 					longitudeAsFloat = GeolocHelper
299 							.parseInternationalDouble(longitude);
300 					if (longitudeAsFloat < -180 || longitudeAsFloat > 180) {
301 						addFieldError(
302 								"longitude",
303 								internationalisationService
304 										.getString("error.longitude.outOfRange"));
305 					}
306 				} catch (Exception e) {
307 					logger.warn("longitude : " + longitude + "is not a number");
308 					addFieldError("longitude",
309 							internationalisationService.getString(
310 									"error.notANumber",
311 									new String[] { "longitude" }));
312 				}
313 			}
314 
315 			Point point = null;
316 			if (latitudeAsFloat != null && longitudeAsFloat != null) {
317 				point = GeolocHelper.createPoint(longitudeAsFloat,
318 						latitudeAsFloat);
319 				return point;
320 			} else {
321 				return null;
322 			}
323 		} catch (Exception e) {
324 			logger.warn("can not determine point for lat/long : " + latitude
325 					+ "/" + longitude);
326 			addFieldError("latitude",
327 					internationalisationService
328 							.getString("error.not.gps.point"));
329 			return null;
330 		}
331 
332 	}
333 
334 	protected long generateGid() {
335 		return IdGenerator.getNextGId();
336 	}
337 
338 	public Long getId() {
339 		return id;
340 	}
341 
342 	public void setId(Long id) {
343 		this.id = id;
344 	}
345 
346 	/**
347 	 * @return the max openstreetmap id found in the Datastore + an increment
348 	 */
349 	
350 
351 	public String doDelete() {
352 		if (openstreetmap!=null){
353 		startTransaction();
354 		try{
355 		openStreetMapDao.remove(openstreetmap);
356 		} catch (Exception e){
357 			logger.error("Can not delete the street : "+e.getMessage(),e);
358 			stackTrace= StringHelper.getStackTraceAsString(e);
359 			rollbackTransaction();
360 			return ERROR;
361 		}
362 		commitTransaction();
363 		return SUCCESS;
364 		} else {
365 			errorMessage="there is no entity to delete";
366 			return ERROR;
367 		}
368 	}
369 
370 
371 	public OpenStreetMap getOpenstreetmap() {
372 		return openstreetmap;
373 	}
374 
375 	public String getLatitude() {
376 		return latitude;
377 	}
378 
379 	public void setLatitude(String latitude) {
380 		this.latitude = latitude;
381 	}
382 
383 	public String getLongitude() {
384 		return longitude;
385 	}
386 
387 	public void setLongitude(String longitude) {
388 		this.longitude = longitude;
389 	}
390 
391 	public String getShape() {
392 		return shape;
393 	}
394 
395 	public void setShape(String shape) {
396 		this.shape = shape;
397 	}
398 
399 	public void setOpenstreetmap(OpenStreetMap openstreetmap) {
400 		this.openstreetmap = openstreetmap;
401 	}
402 
403 	public void setopenstreetmaps(OpenStreetMap openstreetmap) {
404 		this.openstreetmap = openstreetmap;
405 	}
406 	
407 	/**
408 	 * @return the errorMessage
409 	 */
410 	public String getErrorMessage() {
411 		return errorMessage;
412 	}
413 
414 	/**
415 	 * @param errorMessage the errorMessage to set
416 	 */
417 	public void setErrorMessage(String errorMessage) {
418 		this.errorMessage = errorMessage;
419 	}
420 
421 	/**
422 	 * @return the stackTrace
423 	 */
424 	public String getStackTrace() {
425 		return stackTrace;
426 	}
427 
428 	/**
429 	 * @param stackTrace the stackTrace to set
430 	 */
431 	public void setStackTrace(String stackTrace) {
432 		this.stackTrace = stackTrace;
433 	}
434 
435 
436 	@Required
437 	public void setOpenStreetMapDao(IOpenStreetMapDao openStreetMapDao) {
438 		this.openStreetMapDao = openStreetMapDao;
439 	}
440 
441 	@Required
442 	public void setCountryDao(CountryDao countryDao) {
443 		this.countryDao = countryDao;
444 	}
445 
446 
447 	@Required
448 	public void setTransactionManager(
449 			PlatformTransactionManager transactionManager) {
450 		this.transactionManager = transactionManager;
451 	}
452 
453 	@Required
454 	public void setInternationalisationService(
455 			IInternationalisationService internationalisationService) {
456 		this.internationalisationService = internationalisationService;
457 	}
458 	
459 	@Required
460 	public void setIdGenerator(IIdGenerator idGenerator) {
461 		IdGenerator = idGenerator;
462 	}
463 
464 	@Required
465 	public void setSolRSynchroniser(ISolRSynchroniser solRSynchroniser) {
466 	    this.solRSynchroniser = solRSynchroniser;
467 	}
468 
469 	
470 
471 }