/** * @description: * @author chenshiqiang E-mail:csqwyyx@163.com * @date 2014年5月1日 下午3:36:30 * @version 1.0 */ package com.csq.thesceneryalong.io.db; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.ReentrantLock; import com.csq.thesceneryalong.models.models.TrackListData; import org.apache.commons.io.FileUtils; import android.text.TextUtils; import com.csq.thesceneryalong.constant.PathConstants; import com.csq.thesceneryalong.db.Track; import com.csq.thesceneryalong.db.TrackDao; import com.csq.thesceneryalong.db.TrackDao.Properties; import com.csq.thesceneryalong.models.events.EventTrackNumChanged; import com.csq.thesceneryalong.models.events.EventTrackUpdated; import com.csq.thesceneryalong.models.models.RecordStatus; import com.csq.thesceneryalong.utils.dbmodel.TrackUtil; import de.greenrobot.dao.query.Query; import de.greenrobot.dao.query.QueryBuilder; import de.greenrobot.dao.query.WhereCondition.StringCondition; import de.greenrobot.event.EventBus; public class TrackDb { // ------------------------ Constants ------------------------ // ------------------------- Fields -------------------------- private static volatile TrackDb instance; public static TrackDb getInstance(){ if(instance == null){ synchronized (TrackDb.class) { instance = new TrackDb(); } } return instance; } private TrackDao dao; /** * 缓存到内存的所有轨迹,必须Track.getId() > 0 */ private TrackMemory trackMemory; // ----------------------- Constructors ---------------------- private TrackDb(){ dao = DbManager.getInstance().getTrackDao(); trackMemory = new TrackMemory(); } // -------- Methods for/from SuperClass/Interfaces ----------- // --------------------- Methods public ---------------------- public void loadAllTrackToMemory(){ trackMemory.loadAllTrackToMemory(); } public long add(Track track){ long id = dao.insert(track); track.setId(id); trackMemory.add(track); EventBus.getDefault().post(new EventTrackNumChanged()); return id; } public void addSome(Collection<Track> tracks){ dao.insertInTx(tracks); //只能重新加载了 trackMemory.loadAllTrackToMemory(); EventBus.getDefault().post(new EventTrackNumChanged()); } public void delete(long trackId){ //数据库删除 dao.deleteByKey(trackId); TrackPointDb.getInstance().deleteByTrackId(trackId); SceneryDb.getInstance().deleteByTrackId(trackId); //缓存删除 Track del = trackMemory.remove(trackId); //轨迹文件夹删除 try { FileUtils.deleteDirectory( new File(PathConstants.getTrackpath() + File.separator + del.getUniqueMack())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } EventBus.getDefault().post(new EventTrackNumChanged()); } /** * @description: 更新轨迹 * @author: chenshiqiang E-mail:csqwyyx@163.com * @param track * @param updateVersion 版本信息是否+1,有些情况可能不需要更新版本号,如轨迹暂停状态改变 */ public void update(Track track, boolean updateVersion){ if(updateVersion){ track.setVersion(track.getVersion() + 1); } dao.update(track); trackMemory.add(track); EventBus.getDefault().post(new EventTrackUpdated(track)); } /** * @description: 停止所有轨迹的记录 * @author: chenshiqiang E-mail:csqwyyx@163.com */ public void stopAllTracks(){ QueryBuilder<Track> qb = dao.queryBuilder(); qb.where(Properties.RecordStatus.notEq(RecordStatus.finished.getValue())); List<Track> uf = qb.list(); if(uf != null && !uf.isEmpty()){ for(Track t : uf){ t.setRecordStatus(RecordStatus.finished.getValue()); } dao.updateInTx(uf); trackMemory.addSome(uf); EventBus.getDefault().post(new EventTrackUpdated(null)); } } /** * @description: 停止某些轨迹 * @author: chenshiqiang E-mail:csqwyyx@163.com * @param trackIds */ public void stopTracks(Collection<Long> trackIds){ QueryBuilder<Track> qb = dao.queryBuilder(); qb.where(Properties.Id.in(trackIds)); List<Track> uf = qb.list(); if(uf != null && !uf.isEmpty()){ for(Track t : uf){ t.setRecordStatus(RecordStatus.finished.getValue()); } dao.updateInTx(uf); trackMemory.addSome(uf); EventBus.getDefault().post(new EventTrackUpdated(null)); } } /** * @description: 通过trackId查询轨迹 * @author: chenshiqiang E-mail:csqwyyx@163.com * @param trackId * @return */ public Track queryById(long trackId){ return trackMemory.getTrack(trackId); } /** * @description: 从数据库查询所有轨迹,按照开始时间降序 * @author: chenshiqiang E-mail:csqwyyx@163.com * @return */ private List<Track> queryAllDescByBeginTimeFromDb(){ QueryBuilder<Track> qb = dao.queryBuilder(); qb.orderDesc(Properties.BeginTime); return qb.list(); } /** * @description: 获取内存缓存的所有轨迹,按照开始时间降序 * @author: chenshiqiang E-mail:csqwyyx@163.com * @return */ public List<Track> queryAllDescByBeginTime(){ return trackMemory.getAllTracks(); } public TrackListData queryAllSelectionDescByBeginTime(String filter){ TrackListData list = TrackListData.createEmptyTrackListData(); List<Track> ll = queryAllDescByBeginTime(); if(ll != null && !ll.isEmpty()){ boolean isFilterEmpty = TextUtils.isEmpty(filter); Track track = null; String lastSection = null; for(int i = 0, num = ll.size() ; i < num ; i++){ track = ll.get(i); if(!isFilterEmpty && !track.getName().contains(filter)){ //被过滤,下一个 continue; } list.tracks.add(track); String cs = TrackUtil.getListSelection(track); if(!cs.equals(lastSection)){ //另一段 lastSection = cs; //保存section++ list.sectionIndices.add(list.tracks.size()-1); list.headLetters.add(cs); } } } return list; } /** * @description: 查询未完成的轨迹 * @author: chenshiqiang E-mail:csqwyyx@163.com * @return */ public Track queryUnFinished(){ QueryBuilder<Track> qb = dao.queryBuilder(); qb.where(Properties.RecordStatus.notEq(RecordStatus.finished.getValue())); qb.orderDesc(Properties.BeginTime); List<Track> ls = qb.list(); if(ls != null && !ls.isEmpty()){ if(ls.size() == 1){ return ls.get(0); }else{ Track uf = ls.remove(0); //停止最近以前的所有轨迹 List<Long> cs = new ArrayList<Long>(); for(Track t : ls){ cs.add(t.getId()); } stopTracks(cs); return uf; } } return null; } /** * @description: 通过唯一标识查询轨迹 * @author: chenshiqiang E-mail:csqwyyx@163.com * @param uniqueMack * @return */ public Track queryByUniqueMack(String uniqueMack){ QueryBuilder<Track> qb = dao.queryBuilder(); qb.where(Properties.UniqueMack.eq(uniqueMack)); List<Track> ls = qb.list(); if(ls == null || ls.isEmpty()){ return null; }else{ return ls.get(0); } } /** * @description: 通过查询语句查询 * @author: chenshiqiang E-mail:csqwyyx@163.com * @param StringCondition 例如:"_ID IN " + "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)" * @return */ public List<Track> queryByStringCondition(String StringCondition){ Query<Track> query = dao.queryBuilder().where( new StringCondition(StringCondition)).build(); return query.list(); } // --------------------- Methods private --------------------- // --------------------- Getter & Setter --------------------- // --------------- Inner and Anonymous Classes --------------- public static class TrackBeginTimeDescComparator implements Comparator<Track>{ @Override public int compare(Track o1, Track o2) { // TODO Auto-generated method stub if(o1.getBeginTime() == o2.getBeginTime()){ return 0 ; }else if(o1.getBeginTime() > o2.getBeginTime()){ return -1; }else{ return 1; } } } public class TrackMemory{ private ReentrantLock lock = new ReentrantLock(); private List<Track> tracks = new LinkedList<Track>(); private HashMap<Long, Track> tracksMap = new HashMap<Long, Track>(); private TrackBeginTimeDescComparator trackBeginTimeDescComparator = new TrackBeginTimeDescComparator(); /** * @description: 加载所有轨迹到内存 * @author: chenshiqiang E-mail:csqwyyx@163.com */ public void loadAllTrackToMemory(){ List<Track> ts = queryAllDescByBeginTimeFromDb(); setTracks(ts, true); } public void setTracks(List<Track> ts, boolean isBeginTimeDesc) { lock.lock(); try { tracks.clear(); tracksMap.clear(); if(ts != null && !ts.isEmpty()){ tracks = ts; if(!isBeginTimeDesc){ Collections.sort(tracks, trackBeginTimeDescComparator); } for(Track t : tracks){ tracksMap.put(t.getId(), t); } } } finally { lock.unlock(); } } public void add(Track track){ lock.lock(); try { if(tracksMap.containsKey(track.getId())){ Track r = tracksMap.remove(track.getId()); tracks.remove(r); } tracks.add(track); Collections.sort(tracks, trackBeginTimeDescComparator); tracksMap.put(track.getId(), track); } finally { lock.unlock(); } } public void addSome(Collection<Track> ts){ lock.lock(); try { for(Track t : ts){ if(tracksMap.containsKey(t.getId())){ Track r = tracksMap.remove(t.getId()); tracks.remove(r); } tracks.add(t); tracksMap.put(t.getId(), t); } Collections.sort(tracks, trackBeginTimeDescComparator); } finally { lock.unlock(); } } public void remove(Track track){ remove(track.getId()); } public Track remove(long trackId){ lock.lock(); try { if(tracksMap.containsKey(trackId)){ Track r = tracksMap.remove(trackId); tracks.remove(r); return r; } } finally { lock.unlock(); } return null; } public List<Track> getAllTracks() { return tracks; } public Track getTrack(long trackId){ return tracksMap.get(trackId); } } }