/[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

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

Legend:
Removed from v.842  
changed lines
  Added in v.1115

  ViewVC Help
Powered by ViewVC 1.1.20