View Javadoc

1   /*
2    * Trip Tracker, a real-time position tracking system for the Internet.
3    * Copyright (C) 2006  Team Trip Tracker
4    *
5    * This program is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License as published by the
7    * Free Software Foundation; either version 2 of the License, or (at your
8    * option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful, but
11   * WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   * General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License along
16   * with this program; if not, write to the Free Software Foundation, Inc.,
17   * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18   */
19  
20  package triptracker.client.net;
21  
22  import static triptracker.core.ConnectionState.*;
23  import static triptracker.core.Protocol.*;
24  
25  import java.io.IOException;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Date;
29  import java.util.List;
30  
31  import triptracker.core.Coordinate;
32  import triptracker.core.Route;
33  import triptracker.core.User;
34  import triptracker.core.Utils;
35  
36  public class MapSocket extends SocketConnection<MapSocketListener> {
37  	/***
38  	 * Logon a user of the type {@link triptracker.core.Protocol#MAPCLIENT}.
39  	 * 
40  	 * @param user username
41  	 * @param pass password
42  	 * @throws IOException on connection failure
43  	 */
44  	public void logon(String user, String pass) throws IOException {
45  		logon(MAPCLIENT, user, pass);
46  	}
47  
48     	/***
49  	 * {@inheritDoc}
50  	 */
51  	@Override
52  	public void addListener(MapSocketListener listener) {
53  		listeners.add(listener);
54  	}
55  	
56     	/***
57  	 * {@inheritDoc}
58  	 */
59  	@Override
60  	public void removeListener(MapSocketListener listener) {
61  		listeners.remove(listener);
62  	}
63  	
64  	/***
65  	 * Send a request for a list of users to the server.
66  	 */
67  	public void getUsers() {
68  		sendMessage(USERS_GET);
69  	}
70  	
71  	public void getUser(int userId) {
72  		sendMessage(USER_GET, userId);
73  	}
74  	
75  	/***
76  	 * Gets complete route from server.
77  	 */
78  	public void getRoute(Route route) {
79  		if (route == null){
80  			routeList(null);
81  			return;
82  		}
83  		sendMessage(ROUTE_GET, route.getRouteId());
84  	}
85  	
86  	/***
87  	 * Sets realtime route to track.
88  	 * 
89  	 * @param route
90  	 */
91  	public void setRealtimeRoute(Route route) {
92  		sendMessage(SET_ROUTE, route.getRouteId(), "x");
93  	}
94  	
95  	/***
96  	 * Gets realtime plotting routes from server.
97  	 */
98  	public void getRealtimeRoutes() {
99  		sendMessage(REALTIME);
100 	}
101 	
102 	/***
103 	 * Publish a connection state change event to all listeners. This notifies
104 	 * the clients that the connection state of the underlying socket has
105 	 * changed.
106 	 * 
107 	 * @param routeId route ID updated
108 	 * @param coord new coordinate
109 	 */
110 	protected void coordReceived(int routeId, Coordinate coord) {
111 		for (MapSocketListener listener : listeners) {
112 			try {
113 				listener.coordReceived(routeId, coord);
114 			} catch (RuntimeException e) {
115 				brokenListener(listener, e);
116 			}
117 		}
118 	}
119 	
120 	/***
121 	 * Publish a connection state change event to all listeners. This notifies
122 	 * the clients that the connection state of the underlying socket has
123 	 * changed.
124 	 * 
125 	 * @param routeId route ID updated
126 	 * @param coord new coordinate
127 	 */
128 	protected void coordsReceived(List<Coordinate> coords) {
129 		for (MapSocketListener listener : listeners) {
130 			try {
131 				listener.coordsReceived(coords);
132 			} catch (RuntimeException e) {
133 				brokenListener(listener, e);
134 			}
135 		}
136 	}
137 	
138 	/***
139 	 * Publish an updated user list event to all listeners.
140 	 * 
141 	 * @param users
142 	 */
143 	protected void usersReceived(List<User> users) {
144 		for (MapSocketListener listener : listeners) {
145 			try {
146 				listener.usersReceived(users);
147 			} catch (RuntimeException e) {
148 				brokenListener(listener, e);
149 			}
150 		}
151 	}
152 	
153 	/***
154 	 * Publish updated user to all listeners
155 	 * @param users
156 	 */
157 	protected void userReceived(User user) {
158 		for (MapSocketListener listener : listeners) {
159 			try {
160 				listener.userReceived(user);
161 			} catch (RuntimeException e) {
162 				brokenListener(listener, e);
163 			}
164 		}
165 	}
166 	
167 	/***
168 	 * Publish a route list update event to all listeners.
169 	 * 
170 	 * @param routeId route ID updated
171 	 * @param coords list of coordinates
172 	 */
173 	protected void routeReceived(int routeId, List<Coordinate> coords) {
174 		for (MapSocketListener listener : listeners) {
175 			try {
176 				listener.routeReceived(routeId, coords);
177 			} catch (RuntimeException e) {
178 				brokenListener(listener, e);
179 			}
180 		}
181 	}
182 	
183 	/***
184 	 * Publish a route list update event to all listeners. 
185 	 * 
186 	 * @param routes received list of routes
187 	 */
188 	protected void routeList(List<Route> routes) {
189 		for (MapSocketListener listener : listeners) {
190 			try {
191 				listener.routeList(routes);
192 			} catch (RuntimeException e) {
193 				brokenListener(listener, e);
194 			}
195 		}
196 	}
197 
198    	/***
199 	 * {@inheritDoc}
200 	 */
201 	@Override
202 	protected boolean messageHandler(String message) {
203 		String[] msg;
204 		int routeId;
205 		double latitude;
206 		double longitude;
207 		String time;
208 		Coordinate coord;
209 		
210 		msg = message.split(DELIMITER, -1);
211 		System.out.println("Message: " + Arrays.toString(msg));
212 
213 		try {
214 			// Handle message based on first field (msg[0]).
215 			switch (Integer.parseInt(msg[0])) {
216 			case AUTH_FAIL: //=-1
217 				connectionUpdate(AUTH_FAILED);
218 				break;
219 			case AUTH_OK: //=0
220 				connectionUpdate(AUTH_SUCCESS);
221 				break;
222 			case COORD_ADD: //=1
223 //				 For plotting one spesific coordinate
224 				routeId = Integer.parseInt(msg[1]);
225 				latitude = Double.parseDouble(msg[2]);
226 				longitude = Double.parseDouble(msg[3]);
227 				time = msg[4];
228 				coord = new Coordinate(latitude, longitude,
229 						Utils.parseDate(time));
230 
231 //				System.out.println("Recieved: RouteId: "  + routeId
232 //						+ " latitude: " + latitude + ", longitude "
233 //						+ longitude + ", tidspunkt: " + time);
234 				coordReceived(routeId, coord);
235 				break;
236 			case COORD_BUFFER_ADD:
237 				routeId = Integer.parseInt(msg[1]);
238 				List<Coordinate> coords = new ArrayList<Coordinate>();
239 				
240 				for (int i = 2; i < msg.length; i += 3) {
241 					latitude = Double.parseDouble(msg[i]);
242 					longitude = Double.parseDouble(msg[i + 1]);
243 					time = msg[i + 2];
244 					coords.add(new Coordinate(latitude, longitude,
245 							Utils.parseDate(time)));
246 				}
247 				
248 				coordsReceived(coords);
249 				break;
250 			case USERS_GET:
251 				List<User> users = new ArrayList<User>();
252 				for (int i = 1; i<msg.length ; i += 2){
253 					int userId = Integer.parseInt(msg[i]);
254 					String username = msg[i+1];
255 					users.add(new User(userId, username, null));
256 				}
257 				usersReceived(users);
258 				break;
259 			case USER_GET:
260 				User user = new User(Integer.parseInt(msg[1]), msg[2]);
261 				userReceived(user);
262 				break;
263 			case ROUTE_GET:
264 				//Recieves full route previously asked for
265 				List<Coordinate> coordList = new ArrayList<Coordinate>();
266 				
267 				routeId = Integer.parseInt(msg[1]);
268 				
269 //				if (msg.length == 3) { 
270 //					routeReceived(routeId,coordList);
271 //					break;
272 //				}
273 //				System.out.println(routeId);
274 //				System.out.println(inStream);
275 //				
276 //				byte[] buffer = new byte[2];
277 //				GZIPInputStream zipin = new GZIPInputStream(inStream);
278 //				zipin.read(buffer);//,0,size);
279 //				System.out.println("Array: " + buffer[0] + " " + buffer[1]);
280 //				String coordBuffer = new String(buffer);
281 //				System.out.println(coordBuffer);
282 				
283 				for (int i = 2; i < msg.length; i += 3) {
284 					latitude = Double.parseDouble(msg[i]);
285 					longitude = Double.parseDouble(msg[i + 1]);
286 					time = msg[i + 2];
287 					
288 					Coordinate coordi = new Coordinate(latitude, longitude,
289 							Utils.parseDate(time));
290 //					System.out.println("Got coordinate: " + ((i + 1) / 3)
291 //							+ " - " + coordi.getX() + ", " + coordi.getY()
292 //							+ ", " + coordi.getDateString());
293 					coordList.add(coordi);
294 				}
295 				routeReceived(routeId, coordList);
296 				break;
297 			case VIEW_ROUTES:
298 				List<Route> routes = new ArrayList<Route>();
299 
300 				if (msg.length == 1) { 
301 					routeList(routes);
302 					break;
303 				}
304 				if (msg.length == 2) { //FIXME Make server not send empty space
305 					routeList(routes);
306 					break;
307 				}
308 				
309 //				System.out.println("msg[1] " + msg[1]);
310 				for (int i = 1; i < msg.length; i += 6) {
311 					routeId = Integer.parseInt(msg[i]);
312 					int userId = Integer.parseInt(msg[i + 1]);
313 					String description = msg[i + 2];
314 					boolean active = Utils.strToBool(msg[i + 3]);
315 					Date date = Utils.parseDate(msg[i + 4]);
316 					boolean visible = Utils.strToBool(msg[i + 5]);
317 					Route route = new Route(routeId, userId, description,
318 							active, visible, date);
319 					routes.add(route);
320 				}
321 				routeList(routes);
322 				break;
323 			case SET_ROUTE:
324 				// TODO Implement: Route not beeing tracked...
325 				break;
326 			case REALTIME:
327 				// TODO implement: Tracker has stopped logging route.
328 				// XXX Same states as SUBSCRIBED and UNSUBSCRIBED?
329 				if (Utils.strToBool(msg[1])) {
330 					connectionUpdate(TRACKING);
331 				} else {
332 					connectionUpdate(WATCHING);
333 				}
334 				break;
335 			default:
336 				System.out.print("Message: " + msg[1]);
337 				break;
338 			}
339 		} catch (NumberFormatException num) {
340 			System.out.println("NumberFormatException: " + num);
341 			num.printStackTrace();
342 		} 
343 		return true;
344 	}	
345 }