/[projects]/android/TrainInfoServiceGoogle/src/dk/thoerup/traininfoservice/StationDAO.java
ViewVC logotype

Diff of /android/TrainInfoServiceGoogle/src/dk/thoerup/traininfoservice/StationDAO.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1080 by torben, Mon Sep 20 20:11:55 2010 UTC revision 1415 by torben, Mon May 2 15:43:42 2011 UTC
# Line 1  Line 1 
1  package dk.thoerup.traininfoservice;  package dk.thoerup.traininfoservice;
2    
3  import java.sql.Connection;  import java.io.IOException;
4  import java.sql.PreparedStatement;  import java.util.ArrayList;
5  import java.sql.ResultSet;  import java.util.Collections;
6  import java.sql.SQLException;  import java.util.Comparator;
7  import java.sql.Statement;  import java.util.HashMap;
8    import java.util.List;
9    import java.util.Map;
10    import java.util.logging.Level;
11  import java.util.logging.Logger;  import java.util.logging.Logger;
12    
13    import javax.jdo.Extent;
14    import javax.jdo.PersistenceManager;
15    import javax.jdo.Query;
16    
17    import net.sf.jsr107cache.Cache;
18    import net.sf.jsr107cache.CacheException;
19    import net.sf.jsr107cache.CacheManager;
20    
21    import com.google.appengine.api.memcache.jsr107cache.GCacheFactory;
22    
23  import dk.thoerup.android.traininfo.common.StationBean;  import dk.thoerup.android.traininfo.common.StationBean;
24  import dk.thoerup.android.traininfo.common.StationBean.StationEntry;  import dk.thoerup.android.traininfo.common.StationEntry;
25    import dk.thoerup.traininfoservice.geo.Geo;
26    import dk.thoerup.traininfoservice.jdo.JdoStationBean;
27    import dk.thoerup.traininfoservice.jdo.PMF;
28    
29  public class StationDAO {  public class StationDAO {
30          final static int LOCATION_LIMIT = 8;          final static int LOCATION_LIMIT = 8;
31          static final Logger logger = Logger.getLogger(StationDAO.class.getName());          static final Logger logger = Logger.getLogger(StationDAO.class.getName());
32                    
33            final int TIMEOUT_SECONDS = 30*60;
34            
35            Cache cache;
36            
37            @SuppressWarnings("unchecked")
38            public StationDAO() {
39            Map props = new HashMap();
40            props.put(GCacheFactory.EXPIRATION_DELTA, TIMEOUT_SECONDS);        
41                    
42                    try {
43                cache = CacheManager.getInstance().getCacheFactory().createCache(props);            
44            } catch (CacheException e) {
45                    logger.log(Level.WARNING, "error creating cache", e);
46            }
47                    
         private StationEntry convertSingleRow(ResultSet res) throws SQLException {  
                 StationEntry station = new StationEntry();  
   
                 station.setId( res.getInt(1) );  
                 station.setName( res.getString(2) );  
                 station.setLatitude( res.getDouble(3) );  
                 station.setLongitude( res.getDouble(4) );  
                 station.setRegional( res.getString(5) );  
                 station.setStrain( res.getString(6) );  
                 station.setMetro( res.getString(7) );  
                 station.setAddress( res.getString(8) );  
                 station.setCalcdist( (int)res.getDouble(9) );  
                   
                 station.setIsRegional( station.getRegional() != null );  
                 station.setIsStrain( station.getStrain() != null );  
                 station.setIsMetro( station.getMetro() != null );  
   
                 return station;  
         }  
   
         private StationBean convertResultset(ResultSet res) throws SQLException {  
                 StationBean stations = new StationBean();  
                 while (res.next()) {  
                         stations.entries.add( convertSingleRow(res) );  
                 }  
                 return stations;  
   
48          }          }
49    
50    
51          public StationEntry getById(int id) throws SQLException {          public StationEntry getById(int id)  {
                 String SQL = "SELECT id,name,latitude,longitude,stationcode_fjrn,stationcode_stog,stationcode_metro,address,0.0 " +  
                 "FROM trainstations WHERE id=" + id + " AND enabled=true";  
   
                 Connection conn = null;  
                 Statement stmt = null;  
                 ResultSet res = null;  
                 StationEntry result;  
52    
53                    PersistenceManager pm = null;
54                    
55                  try {                  try {
56                          conn = DBConnection.getConnection();                          pm = PMF.get().getPersistenceManager();
57                            JdoStationBean bean =pm.getObjectById(JdoStationBean.class, new Integer(id) );
58                          stmt = conn.createStatement();                          return bean.toStationEntry();
                         res = stmt.executeQuery(SQL);            
                         res.next();  
                         result = convertSingleRow(res);  
59                  } finally {                  } finally {
60                          if (res != null)                          pm.close();
                                 res.close();  
                         if (stmt != null)  
                                 stmt.close();  
                         if (conn != null)  
                                 conn.close();  
61                  }                  }
   
                 return result;  
62          }          }
63    
64          /*          /* damn that JDO sucks so we to the filtering in java-code */
65           * this code requires theses statements are run on database in order to do ILIKE searches against aliases (which is defines as array of varchar(64) )          public StationBean getByName(String searchname) {
66           *     create function rlike(text,text) returns bool as                          
67           *     'select $2 ilike $1' language sql strict immutable;                  List<JdoStationBean> beanList = getAllStations();
          *     create operator ~~~ (procedure = rlike, leftarg = text, rightarg = text, commutator = ~~);  
          */  
         public StationBean getByName(String name) throws SQLException {  
                 String SQL = "SELECT id,name,latitude,longitude,stationcode_fjrn,stationcode_stog, stationcode_metro, address, 0.0 " +  
                 "FROM trainstations " +  
                 "WHERE (name ILIKE ? OR ? ~~~ ANY(aliases)) AND enabled = true " +  
                 "ORDER BY name ";  
   
   
                 StationBean result;  
                 Connection conn = null;  
                 PreparedStatement stmt = null;  
                 ResultSet res = null;  
                 try {  
                         conn = DBConnection.getConnection();  
                         stmt = conn.prepareStatement(SQL);  
68    
                         stmt.setString(1, name + "%");  
                         stmt.setString(2, name + "%");  
69    
70                          res = stmt.executeQuery();                  StationBean stationBean = new StationBean();
                         result = convertResultset(res);  
71    
72                  } finally {                  searchname = searchname.toLowerCase();
73                          if (res != null)                  for(JdoStationBean bean : beanList) {
74                                  res.close();                          if (bean.getName().toLowerCase().startsWith(searchname)) {
75                          if (stmt != null)                                  stationBean.entries.add( bean.toStationEntry() );
76                                  stmt.close();                          } else {
77                          if (conn!= null)                                  for (String alias : bean.aliases ) {
78                                  conn.close();                                          if (alias.toLowerCase().startsWith(searchname)) {
79                                                    stationBean.entries.add( bean.toStationEntry() );
80                                            }
81                                    }
82                            }
83                  }                  }
                 return result;  
         }  
84    
85          //the "hack" with max 0.4 degrees latitude and 0.75 degrees longitude is only valid since we only service danish trains,                  Collections.sort(stationBean.entries, new Comparator<StationEntry>() {
86          // in denmark 0.4dg latitude ~ 44km, 0.75dg longitude ~ 47km                          @Override
87                            public int compare(StationEntry arg0, StationEntry arg1) {
88                                    return arg0.getName().compareTo( arg1.getName() );
89                            }                              
90                    });
91    
92          // the ultra fast method  (and only slightly inaccurate as long as we only cover a limited geographically area)                  return stationBean;                    
         // is using an aproximation of the length of 1 latitude degree and 1 longitude degree and just use pythagoras to  
         // calculate the distance:  
         //     sqrt( power(abs(latitude-?)*111320, 2) + power(abs(longitude-?)*63000,2) )::int as calcdist  
93    
94          public StationBean getByLocationWorker(double latitude, double longitude, boolean geolimit) throws SQLException {          }
95            
96            @SuppressWarnings("unchecked")
97            public List<JdoStationBean> getAllStations() {
98                    final String key = "allstations";
99                    List<JdoStationBean> result = (List<JdoStationBean>) cache.get(key);
100                                    
101                  String limitExpression = (geolimit == true) ? "AND abs(latitude-?)<0.4 AND abs(longitude-?)<0.75 " : "";                  if (result == null) {
102                            logger.info("getAllStations Cache miss");
103                            
104                            PersistenceManager pm = null;
105                            
106                            try {
107                                    pm = PMF.get().getPersistenceManager();
108                                    Extent<JdoStationBean> all = pm.getExtent(JdoStationBean.class, false);
109                                    
110                                    result = new ArrayList<JdoStationBean>();
111                                    for (JdoStationBean station : all) {
112                                            result.add(station);
113                                    }
114                                    
115                                    cache.put(key, result);
116                                    
117                            } finally {
118                                    pm.close();
119                            }
120                    } else {
121                            logger.info("getAllStations Cache hit");
122                    }
123                                    
                 String SQL = "SELECT id,name,latitude,longitude,stationcode_fjrn,stationcode_stog, stationcode_metro, address, " +  
                         "earth_distance( earth_coord, ll_to_earth(?,?))::int AS calcdist " +  
                         "FROM trainstations " +  
                         "WHERE enabled = true " + limitExpression +  
                         "ORDER BY calcdist ASC " +  
                         "LIMIT " + LOCATION_LIMIT;  
   
   
124                                    
                 StationBean result;  
                 Connection conn = null;  
                 PreparedStatement stmt = null;  
                 ResultSet res = null;  
                 try {  
                         conn = DBConnection.getConnection();  
                         stmt = conn.prepareStatement(SQL);  
                         stmt.setDouble(1, latitude);  
                         stmt.setDouble(2, longitude);  
                         if (geolimit == true) {  
                                 stmt.setDouble(3, latitude);  
                                 stmt.setDouble(4, longitude);  
                         }  
                         res = stmt.executeQuery();  
                         result = convertResultset(res);  
125                                    
                 } finally {  
                         if (res != null)  
                                 res.close();  
                         if (stmt != null)  
                                 stmt.close();  
                         if (conn!= null)  
                                 conn.close();  
                 }  
126                  return result;                  return result;
127                    
128          }          }
129                    
130          public StationBean getByLocation(double latitude, double longitude) throws SQLException {  
131                  StationBean result = getByLocationWorker(latitude, longitude, true);          //String limitExpression = (geolimit == true) ? "AND abs(latitude-?)<0.4 AND abs(longitude-?)<0.75 " : "";
132            /*
133            public List<JdoStationBean> getByLocationList(double latitude, double longitude, boolean geolimit)  {
134            
135                    PersistenceManager pm = null;
136                    final double LAT = 0.4;
137                    final double LNG = 0.75;
138                                    
139                  if (result.entries.size() < LOCATION_LIMIT) { //failover                  try {
140                          logger.info("getByLocation failover: " +latitude + "," + longitude);                          pm = PMF.get().getPersistenceManager();
141                            Query q = pm.newQuery(JdoStationBean.class);
142                            
143                            
144                                                    
145                          result = getByLocationWorker(latitude, longitude, false);                          if (geolimit == true) {
146                                    double minLat = latitude - LAT;
147                                    double maxLat = latitude + LAT;
148                                    
149                                    //DAMN JDO implementation only allows us to compare on one parameter
150    
151                                    String filter = String.format("latitude > %f && latitude < %f", minLat, maxLat);
152                                    
153                                    q.setFilter( filter );
154                            }
155                            
156                            List<JdoStationBean> beanList = (List<JdoStationBean>) q.execute();                    
157                            
158                            logger.info("beanList size " + beanList.size());
159                            
160                            return beanList;
161                    } finally {
162                            pm.close();
163                  }                  }
164            }*/
165    
166    
167            public StationBean getByLocation(double latitude, double longitude)  {
168                                    
169                  return result;                  List<JdoStationBean> beanList = getAllStations();
         }  
           
           
170    
171          public StationBean getByList(String list) throws SQLException {                  StationBean stationBean = new StationBean();                    
                 String SQL = "SELECT id,name,latitude,longitude,stationcode_fjrn,stationcode_stog,stationcode_metro, address,0.0 " +  
                 "FROM trainstations " +  
                 "WHERE id IN " + list + " AND enabled = true " +  
                 "ORDER BY name ";  
   
                 Connection conn = null;  
                 Statement stmt = null;  
                 ResultSet res = null;  
                 StationBean result;  
172    
173                  try {  
174                          conn = DBConnection.getConnection();                  Geo location = new Geo(latitude,longitude);
175                          stmt = conn.createStatement();                  for(JdoStationBean bean : beanList) {
176                          res = stmt.executeQuery(SQL);                          double meter = Geo.distanceKM( location, new Geo(bean.getLatitude(), bean.getLongitude() )) * 1000.0;
177                          result = convertResultset(res);  
178                  } finally {                          bean.distance = (int) meter;
                         if (res != null)  
                                 res.close();  
                         if (stmt != null)  
                                 stmt.close();  
                         if (conn!= null)  
                                 conn.close();  
179                  }                  }
180    
                 return result;  
181    
182                    Collections.sort(beanList, new Comparator<JdoStationBean>() {
183                            @Override
184                            public int compare(JdoStationBean o1, JdoStationBean o2) {
185                                    if (o1.distance < o2.distance) {
186                                            return -1;
187                                    } else if (o1.distance > o2.distance) {
188                                            return 1;
189                                    } else {
190                                            return 0;
191                                    }
192                            }
193                    });
194    
195                    for (int i=0; i<LOCATION_LIMIT && i<beanList.size(); i++) {
196                            stationBean.entries.add( beanList.get(i).toStationEntry() );
197                    }
198    
199                    return stationBean;                    
200          }          }
201          public static String getStationName(int stationID) {          
                 String station = "";  
202    
203                  Connection conn = null;          @SuppressWarnings("unchecked")
204            public StationBean getByList(String list)  {
205                    PersistenceManager pm = null;
206                    
207                  try {                  try {
208                          conn = DBConnection.getConnection();                          String parts[] = list.split(",");
209                          Statement stmt = conn.createStatement();                          
210                          ResultSet rs = stmt.executeQuery("SELECT name FROM trainstations WHERE id=" + stationID);                          StringBuilder filter = new StringBuilder();
211                          if (rs.next()) {                          
212                                  station = rs.getString(1);                          for(String part : parts)  {
213                                    if (filter.length() > 0) {
214                                            filter.append( " || " );
215                                    }
216                                    filter.append("id == ").append(part);
217                            }                      
218                            
219                            
220                            pm = PMF.get().getPersistenceManager();
221                            Query q = pm.newQuery(JdoStationBean.class);
222                            q.setFilter( filter.toString() );
223                            q.setOrdering("name");
224                            
225                            List<JdoStationBean> beanList = (List<JdoStationBean>) q.execute();
226                            
227                            StationBean stationBean = new StationBean();
228                            
229                            for(JdoStationBean bean : beanList) {
230                                    stationBean.entries.add( bean.toStationEntry() );
231                          }                          }
232    
233                  } catch (Exception e) {                          return stationBean;                    
234                  } finally {                  } finally {
235                          try {                          pm.close();
                                 if (conn != null && !conn.isClosed())  
                                         conn.close();  
                         } catch (Exception e) {}  
236                  }                  }
237    
                 return station;  
238          }          }
239    
         public int getIdByName(String name) throws SQLException {  
                 String SQL = "SELECT id,name,latitude,longitude,stationcode_fjrn,stationcode_stog, stationcode_metro, address, 0.0 " +  
                 "FROM trainstations " +  
                 "WHERE name = ?  AND enabled = true " +  
                 "LIMIT 1 ";  
   
                 StationBean result;  
                 Connection conn = null;  
                 PreparedStatement stmt = null;  
                 ResultSet res = null;  
                 try {  
                         conn = DBConnection.getConnection();  
                         stmt = conn.prepareStatement(SQL);  
   
                         stmt.setString(1, name );  
   
                         res = stmt.executeQuery();  
                         result = convertResultset(res);  
240    
241            @SuppressWarnings("unchecked")
242            public int getIdByName(String name)  {
243                    
244                    List<JdoStationBean> beanList = null;
245                    
246                    PersistenceManager pm = null;
247                    
248                    try {
249                            
250                            String filter = " name == '" + name + "'";
251                            
252                            pm = PMF.get().getPersistenceManager();
253                            Query q = pm.newQuery(JdoStationBean.class);
254                            q.setFilter(filter);
255                            
256                            beanList = (List<JdoStationBean>) q.execute();
257                            
258                            StationBean stationBean = new StationBean();
259                            
260                            for(JdoStationBean bean : beanList) {
261                                    stationBean.entries.add( bean.toStationEntry() );
262                            }                      
263                            
264                            
265                  } finally {                  } finally {
266                          if (res != null)                          pm.close();
                                 res.close();  
                         if (stmt != null)  
                                 stmt.close();  
                         if (conn!= null)  
                                 conn.close();  
267                  }                  }
268    
269                  if (result.entries.size() == 1) {                  if ( beanList != null && beanList.size()  == 1) {
270                          return result.entries.get(0).getId();                          return (int) beanList.get(0).getId();
271                  } else {                  } else {
272                          return -1;                          return -1;
273                  }                  }
274          }          }
275            
276            @SuppressWarnings("unchecked")
277            public int saveStations(StationBean stationBean) throws IOException {
278                    PersistenceManager pm = null;
279                    
280                    try {
281                            pm = PMF.get().getPersistenceManager();
282                            
283                            List oldEntries = (List) pm.newQuery(JdoStationBean.class).execute();
284                            pm.deletePersistentAll(oldEntries);
285                            
286                            List<JdoStationBean> jdoList = new ArrayList<JdoStationBean>();
287                            for (StationEntry station : stationBean.entries) {
288                                    JdoStationBean jdoBean = JdoStationBean.fromStationEntry(station);
289                                    
290                                    jdoList.add(jdoBean);
291                                    
292                            }
293                            pm.makePersistentAll(jdoList);
294                            
295                            return jdoList.size();
296                            
297                    } finally {
298                            pm.close();
299                    }
300            }
301            
302  }  }

Legend:
Removed from v.1080  
changed lines
  Added in v.1415

  ViewVC Help
Powered by ViewVC 1.1.20