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  /**
24   *
25   */
26  package com.gisgraphy.reversegeocoding;
27  
28  import java.io.ByteArrayOutputStream;
29  import java.io.OutputStream;
30  import java.io.UnsupportedEncodingException;
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  import javax.annotation.Resource;
37  
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  import org.springframework.beans.factory.annotation.Autowired;
41  import org.springframework.stereotype.Service;
42  import org.springframework.util.Assert;
43  
44  import com.gisgraphy.addressparser.Address;
45  import com.gisgraphy.addressparser.AddressResultsDto;
46  import com.gisgraphy.addressparser.AddressResultsDtoSerializer;
47  import com.gisgraphy.domain.geoloc.entity.OpenStreetMap;
48  import com.gisgraphy.domain.repository.IOpenStreetMapDao;
49  import com.gisgraphy.domain.valueobject.Constants;
50  import com.gisgraphy.serializer.common.UniversalSerializerConstant;
51  import com.gisgraphy.service.IStatsUsageService;
52  import com.gisgraphy.service.ServiceException;
53  import com.gisgraphy.stats.StatsUsageType;
54  import com.vividsolutions.jts.geom.Point;
55  
56  /**
57   * Default (threadsafe) implementation of {@link IReverseGeocodingService}.
58   * 
59   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
60   * 
61   */
62  @Service
63  public class ReverseGeocodingService implements IReverseGeocodingService {
64  
65  	private static final ArrayList<Address> NO_ADDRESS_LIST = new ArrayList<Address>();
66  
67  	@Autowired
68  	protected IOpenStreetMapDao openStreetMapDao;
69  
70  	@Resource
71  	protected IStatsUsageService statsUsageService;
72  	
73  	@Autowired
74  	protected AddressHelper addressHelper;
75  	
76  	AddressResultsDtoSerializer addressResultsDtoSerializer = new AddressResultsDtoSerializer();
77  
78  	/**
79  	 * The logger
80  	 */
81  	protected static final Logger logger = LoggerFactory
82  			.getLogger(ReverseGeocodingService.class);
83  
84  
85  	public AddressResultsDto executeQuery(ReverseGeocodingQuery query)
86  			throws ServiceException {
87  		Assert.notNull(query, "Can not execute a null query");
88  		Point point = query.getPoint();
89  		Assert.notNull(point, "Can not execute a query without a valid point");
90  		long start = System.currentTimeMillis();
91  		statsUsageService.increaseUsage(StatsUsageType.REVERSEGEOCODING);
92  		OpenStreetMap openStreetMap = openStreetMapDao.getNearestRoadFrom(point);
93  		if (openStreetMap==null){
94  			logger.debug("no road found, try to search deeper");
95  			openStreetMap =openStreetMapDao.getNearestFrom(point);
96  		}
97  		if (openStreetMap!= null){
98  			logger.debug("found a street "+openStreetMap);
99  			if (openStreetMap.getHouseNumbers()!=null && openStreetMap.getHouseNumbers().size() >=1 ){
100 				logger.debug("the street has "+openStreetMap.getHouseNumbers().size()+" housenumbers");
101 				HouseNumberDistance houseNumberDistance = addressHelper.getNearestHouse(openStreetMap.getHouseNumbers(), point);
102 				if (houseNumberDistance!=null){
103 					Address address = addressHelper.buildAddressFromHouseNumberDistance(houseNumberDistance);
104 					if (address!=null){
105 						logger.debug("found an address at a house number level");
106 						List<Address> addresses = new ArrayList<Address>();
107 						addresses.add(address);
108 						long end = System.currentTimeMillis();
109 						long qTime = end - start;
110 						logger.info(query + " took " + (qTime) + " ms and returns a result");
111 						return new AddressResultsDto(addresses, qTime);
112 					}  else {
113 						logger.debug("found an address at a street  level");
114 						List<Address> addresses = new ArrayList<Address>();
115 						addresses.add(address);
116 						long end = System.currentTimeMillis();
117 						long qTime = end - start;
118 						logger.info(query + " took " + (qTime) + " ms and returns a result");
119 						return new AddressResultsDto(addresses, qTime);
120 					}
121 				}
122 			} else {
123 				logger.debug("the street has no housenumbers");
124 				Address address = addressHelper.buildAddressFromOpenstreetMapAndPoint(openStreetMap,point);
125 				if (address!=null){
126 					List<Address> addresses = new ArrayList<Address>();
127 					addresses.add(address);
128 					long end = System.currentTimeMillis();
129 					long qTime = end - start;
130 					logger.info(query + " took " + (qTime) + " ms and returns a result");
131 					return new AddressResultsDto(addresses, qTime);
132 				} 
133 			}
134 		} 
135 		long end = System.currentTimeMillis();
136 		long qTime = end - start;
137 		logger.info(query + " took " + (qTime) + " ms and doeant returns no result");
138 		return new AddressResultsDto(NO_ADDRESS_LIST, qTime);
139 	}
140 
141 	/*
142 	 * (non-Javadoc)
143 	 * 
144 	 * @see com.gisgraphy.domain.geoloc.service.IQueryProcessor#executeAndSerialize(com.gisgraphy.domain.geoloc.service.AbstractGisQuery,
145 	 *      java.io.OutputStream)
146 	 */
147 	public void executeAndSerialize(ReverseGeocodingQuery query, OutputStream outputStream)
148 			throws ServiceException {
149 		Assert.notNull(query, "Can not execute a null query");
150 		Assert.notNull(outputStream,
151 				"Can not serialize into a null outputStream");
152 	AddressResultsDto AddressResultDto = executeQuery(query);
153 	Map<String, Object> extraParameter = new HashMap<String, Object>();
154 	extraParameter.put(UniversalSerializerConstant.CALLBACK_METHOD_NAME, query.getCallback());
155 	addressResultsDtoSerializer.serialize(outputStream, query.getOutputFormat(), AddressResultDto, false,extraParameter);
156 	}
157 
158 	/*
159 	 * (non-Javadoc)
160 	 * 
161 	 * @see com.gisgraphy.domain.geoloc.service.IQueryProcessor#executeQueryToString(com.gisgraphy.domain.geoloc.service.AbstractGisQuery)
162 	 */
163 	public String executeQueryToString(ReverseGeocodingQuery query)
164 			throws ServiceException {
165 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
166 		executeAndSerialize(query, outputStream);
167 		try {
168 			return outputStream.toString(Constants.CHARSET);
169 		} catch (UnsupportedEncodingException e) {
170 			throw new RuntimeException("unknow encoding "+Constants.CHARSET);
171 		}
172 	}
173 
174 
175 }