package de.westnordost.streetcomplete.data.osm.persist; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; import java.util.Date; import java.util.List; import javax.inject.Inject; import de.westnordost.streetcomplete.data.AQuestDao; import de.westnordost.streetcomplete.data.WhereSelectionBuilder; import de.westnordost.streetcomplete.data.osm.ElementGeometry; import de.westnordost.streetcomplete.data.osm.OsmQuest; import de.westnordost.streetcomplete.data.QuestStatus; import de.westnordost.streetcomplete.data.osm.changes.StringMapChanges; import de.westnordost.streetcomplete.data.osm.OsmElementQuestType; import de.westnordost.streetcomplete.data.QuestTypes; import de.westnordost.streetcomplete.util.Serializer; import de.westnordost.osmapi.map.data.BoundingBox; import de.westnordost.osmapi.map.data.Element; public class OsmQuestDao extends AQuestDao<OsmQuest> { private final Serializer serializer; private final QuestTypes questTypeList; private final SQLiteStatement add, replace; @Inject public OsmQuestDao(SQLiteOpenHelper dbHelper, Serializer serializer, QuestTypes questTypeList) { super(dbHelper); this.serializer = serializer; this.questTypeList = questTypeList; String sql = OsmQuestTable.NAME + " ("+ OsmQuestTable.Columns.QUEST_ID+","+ OsmQuestTable.Columns.QUEST_TYPE+","+ OsmQuestTable.Columns.QUEST_STATUS+","+ OsmQuestTable.Columns.TAG_CHANGES+","+ OsmQuestTable.Columns.LAST_UPDATE+","+ OsmQuestTable.Columns.ELEMENT_ID+","+ OsmQuestTable.Columns.ELEMENT_TYPE+ ") values (?,?,?,?,?,?,?);"; SQLiteDatabase db = dbHelper.getWritableDatabase(); add = db.compileStatement("INSERT OR IGNORE INTO " + sql); replace = db.compileStatement("INSERT OR REPLACE INTO " + sql); } public List<OsmQuest> getAll(BoundingBox bbox, QuestStatus status, String questTypeName, Element.Type elementType, Long elementId) { WhereSelectionBuilder qb = new WhereSelectionBuilder(); addBBox(bbox, qb); addQuestStatus(status, qb); addQuestType(questTypeName, qb); addElementType(elementType, qb); addElementId(elementId, qb); return getAllThings(getMergedViewName(), null, qb, new CreateFromCursor<OsmQuest>() { @Override public OsmQuest create(Cursor cursor) { return createObjectFrom(cursor); } }); } private void addQuestType(String questTypeName, WhereSelectionBuilder builder) { if(questTypeName != null) { builder.appendAnd(OsmQuestTable.Columns.QUEST_TYPE + " = ?", questTypeName); } } private void addElementType(Element.Type elementType, WhereSelectionBuilder builder) { if(elementType != null) { String elementKeyName = elementType.name(); builder.appendAnd(OsmQuestTable.Columns.ELEMENT_TYPE + " = ?", elementKeyName); } } private void addElementId(Long elementId, WhereSelectionBuilder builder) { if(elementId != null) { String elementIdStr = String.valueOf(elementId); builder.appendAnd(OsmQuestTable.Columns.ELEMENT_ID + " = ?", elementIdStr); } } @Override protected String getTableName() { return OsmQuestTable.NAME; } @Override protected String getMergedViewName() { return OsmQuestTable.NAME_MERGED_VIEW; } @Override protected String getIdColumnName() { return OsmQuestTable.Columns.QUEST_ID; } @Override protected String getLatitudeColumnName() { return ElementGeometryTable.Columns.LATITUDE; } @Override protected String getLongitudeColumnName() { return ElementGeometryTable.Columns.LONGITUDE; } @Override protected String getQuestStatusColumnName() { return OsmQuestTable.Columns.QUEST_STATUS; } @Override protected synchronized long executeInsert(OsmQuest quest, boolean replace) { SQLiteStatement stmt = replace ? this.replace : this.add; if(quest.getId() != null) { stmt.bindLong(1, quest.getId()); } else { stmt.bindNull(1); } stmt.bindString(2, quest.getType().getClass().getSimpleName()); stmt.bindString(3, quest.getStatus().name()); if(quest.getChanges() != null) { stmt.bindBlob(4, serializer.toBytes(quest.getChanges())); } else { stmt.bindNull(4); } stmt.bindLong(5, quest.getLastUpdate().getTime()); stmt.bindLong(6, quest.getElementId()); stmt.bindString(7, quest.getElementType().name()); long result = stmt.executeInsert(); stmt.clearBindings(); return result; } @Override protected ContentValues createFinalContentValuesFrom(OsmQuest quest) { ContentValues values = new ContentValues(); values.put(OsmQuestTable.Columns.QUEST_TYPE, quest.getType().getClass().getSimpleName()); values.put(OsmQuestTable.Columns.ELEMENT_ID, quest.getElementId()); values.put(OsmQuestTable.Columns.ELEMENT_TYPE, quest.getElementType().name()); return values; } @Override protected ContentValues createNonFinalContentValuesFrom(OsmQuest quest) { ContentValues values = new ContentValues(); values.put(OsmQuestTable.Columns.QUEST_STATUS, quest.getStatus().name()); values.put(OsmQuestTable.Columns.LAST_UPDATE, quest.getLastUpdate().getTime()); if(quest.getChanges() != null) { values.put(OsmQuestTable.Columns.TAG_CHANGES, serializer.toBytes(quest.getChanges())); } return values; } @Override protected OsmQuest createObjectFrom(Cursor cursor) { int colQuestId = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.QUEST_ID), colElementId = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.ELEMENT_ID), colElementType = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.ELEMENT_TYPE), colQuestStatus = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.QUEST_STATUS), colQuestType = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.QUEST_TYPE), colChanges = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.TAG_CHANGES), colLastChange = cursor.getColumnIndexOrThrow(OsmQuestTable.Columns.LAST_UPDATE); long questId = cursor.getLong(colQuestId); long elementId = cursor.getLong(colElementId); Element.Type elementType = Element.Type.valueOf(cursor.getString(colElementType)); QuestStatus questStatus = QuestStatus.valueOf(cursor.getString(colQuestStatus)); String questTypeName = cursor.getString(colQuestType); OsmElementQuestType questType = (OsmElementQuestType) questTypeList.forName(questTypeName); if(questType == null) { throw new IllegalArgumentException("The quest type " + questTypeName + " does not exist!"); } StringMapChanges changes = null; if(!cursor.isNull(colChanges)) { changes = serializer.toObject(cursor.getBlob(colChanges), StringMapChanges.class); } ElementGeometry geometry = ElementGeometryDao.createObjectFrom(serializer, cursor); Date lastChange = new Date(cursor.getLong(colLastChange)); return new OsmQuest(questId, questType, elementType, elementId, questStatus, changes, lastChange, geometry); } }