Commit 03a10fc8 authored by Mudar Noufal's avatar Mudar Noufal

Handle API dataType field

distinguish data/map types, to allow showing multiple datasets on the
same map section
parent 01fb1a36
......@@ -64,6 +64,13 @@ public class Const {
public interface ApiValues {
String TYPE_PLACEMARKS = "placemarks";
String TYPE_SHAPES = "shapes";
// There's a slight difference between mapType and dataType
String TYPE_FIRE_HALLS = MapTypes.FIRE_HALLS;
String TYPE_SPVM_STATIONS = MapTypes.SPVM_STATIONS;
String TYPE_WATER_SUPPLIES = MapTypes.WATER_SUPPLIES;
String TYPE_AIR_CONDITIONING = "air_conditioning";
String TYPE_EMERGENCY_HOSTELS = MapTypes.EMERGENCY_HOSTELS;
String TYPE_HOSPITALS = MapTypes.HOSPITALS;
}
public interface BundleKeys {
......@@ -92,7 +99,7 @@ public class Const {
* Database
*/
public static final String DATABASE_NAME = "mtlaucasou.realm";
public static final int DATABASE_VERSION = 10;
public static final int DATABASE_VERSION = 11;
/**
* Settings, SharedPreferences
......
......@@ -27,6 +27,9 @@ import android.app.Application;
import com.crashlytics.android.Crashlytics;
import java.io.FileNotFoundException;
import ca.mudar.mtlaucasou.data.RealmSchemaMigration;
import ca.mudar.mtlaucasou.data.UserPrefs;
import ca.mudar.mtlaucasou.service.SyncService;
import ca.mudar.mtlaucasou.util.LangUtils;
......@@ -61,9 +64,14 @@ public class MtlAuCasOuApp extends Application {
.name(Const.DATABASE_NAME)
.schemaVersion(Const.DATABASE_VERSION)
.build();
try {
Realm.migrateRealm(config, new RealmSchemaMigration());
} catch (FileNotFoundException ignored) {
// If the Realm file doesn't exist, just ignore.
}
Realm.setDefaultConfiguration(config);
startService(SyncService.getIntent(this));
startService(SyncService.newIntent(this));
}
private void setupLeakCanary() {
......
......@@ -41,12 +41,13 @@ public class RealmQueries {
* Delete data from the Realm db
*
* @param realm
* @param mapType
* @param dataType
*/
public static void clearMapData(Realm realm, @MapType String mapType) {
public static void clearMapData(Realm realm, String dataType) {
realm.beginTransaction();
queryPlacemarksByMapType(realm, mapType)
realm.where(RealmPlacemark.class)
.equalTo(RealmPlacemark.FIELD_DATA_TYPE, dataType)
.findAll()
.deleteAllFromRealm();
......@@ -61,13 +62,17 @@ public class RealmQueries {
* @param mapType
* @param transaction
*/
public static void cacheMapData(Realm realm, List<PointsFeature> pointsFeatures, @MapType String mapType, boolean transaction) {
public static void cacheMapData(Realm realm, List<PointsFeature> pointsFeatures,
@MapType String mapType, String dataType, boolean transaction) {
if (transaction) {
realm.beginTransaction();
}
// Loop over results, convert GeoJSON to Realm then add to db
for (PointsFeature feature : pointsFeatures) {
realm.copyToRealm(new RealmPlacemark.Builder(feature, mapType).build());
realm.copyToRealm(new RealmPlacemark.Builder(feature)
.mapType(mapType)
.dataType(dataType)
.build());
}
if (transaction) {
......
/*
Montréal Just in Case
Copyright (C) 2011 Mudar Noufal <mn@mudar.ca>
Geographic locations of public safety services. A Montréal Open Data
project.
This file is part of Montréal Just in Case.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.mudar.mtlaucasou.data;
import ca.mudar.mtlaucasou.model.RealmPlacemark;
import io.realm.DynamicRealm;
import io.realm.DynamicRealmObject;
import io.realm.RealmMigration;
import io.realm.RealmObjectSchema;
import io.realm.RealmSchema;
import static ca.mudar.mtlaucasou.util.LogUtils.makeLogTag;
public class RealmSchemaMigration implements RealmMigration {
private static final String TAG = makeLogTag("RealmSchemaMigration");
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
final RealmSchema schema = realm.getSchema();
if (oldVersion == 10 && newVersion == 11) {
/**
* v11 added string field `dataType` to v10
*/
final RealmObjectSchema placemarkSchema = schema.get("RealmPlacemark");
// Add the `dataType` field, and set its value to `mapType`.
// Placemarks in v10 didn't have mixed types yet.
placemarkSchema
.addField(RealmPlacemark.FIELD_DATA_TYPE, String.class)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
obj.set(RealmPlacemark.FIELD_DATA_TYPE,
obj.getString(RealmPlacemark.FIELD_MAP_TYPE));
}
});
oldVersion++;
}
}
}
......@@ -35,6 +35,8 @@ public class RealmPlacemark extends RealmObject implements
@Ignore
public static final String FIELD_MAP_TYPE = "mapType";
@Ignore
public static final String FIELD_DATA_TYPE = "dataType";
@Ignore
public static final String FIELD_COORDINATES = "coordinates";
@Ignore
public static final String FIELD_COORDINATES_LAT = "coordinates.lat";
......@@ -47,6 +49,7 @@ public class RealmPlacemark extends RealmObject implements
@MapType
@Index
private String mapType;
private String dataType;
private PlacemarkProperties properties;
private LongitudeLatitude coordinates;
......@@ -62,6 +65,7 @@ public class RealmPlacemark extends RealmObject implements
private RealmPlacemark(Builder builder) {
this.id = builder.id;
this.mapType = builder.mapType;
this.dataType = builder.dataType;
this.properties = builder.properties;
this.coordinates = builder.coordinates;
}
......@@ -99,6 +103,14 @@ public class RealmPlacemark extends RealmObject implements
this.mapType = mapType;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public PlacemarkProperties getProperties() {
return properties;
}
......@@ -122,12 +134,12 @@ public class RealmPlacemark extends RealmObject implements
private String id;
@MapType
private String mapType;
private String dataType;
private PlacemarkProperties properties;
private LongitudeLatitude coordinates;
public Builder(PointsFeature pointsFeature, @MapType String mapType) {
public Builder(PointsFeature pointsFeature) {
this.id = pointsFeature.getId();
this.mapType = mapType;
this.properties = new PlacemarkProperties.Builder(pointsFeature.getProperties())
.build();
......@@ -135,6 +147,18 @@ public class RealmPlacemark extends RealmObject implements
.build();
}
public Builder mapType(@MapType String mapType) {
this.mapType = mapType;
return this;
}
public Builder dataType(String dataType) {
this.dataType = dataType;
return this;
}
public RealmPlacemark build() {
return new RealmPlacemark(this);
}
......
......@@ -23,6 +23,8 @@
package ca.mudar.mtlaucasou.model.jsonapi;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
import ca.mudar.mtlaucasou.model.MapType;
......@@ -31,7 +33,9 @@ public class Attributes {
private String title;
private Date created;
private Date updated;
private String type;
@SerializedName("type")
private String dataType;
private String mapType;
public String getTitle() {
return title;
......@@ -45,8 +49,12 @@ public class Attributes {
return updated;
}
public String getDataType() {
return dataType;
}
@MapType
public String getType() {
return type;
public String getMapType() {
return mapType;
}
}
......@@ -42,6 +42,7 @@ import ca.mudar.mtlaucasou.data.RealmQueries;
import ca.mudar.mtlaucasou.data.UserPrefs;
import ca.mudar.mtlaucasou.model.MapType;
import ca.mudar.mtlaucasou.model.geojson.PointsFeatureCollection;
import ca.mudar.mtlaucasou.model.jsonapi.Attributes;
import ca.mudar.mtlaucasou.model.jsonapi.DataItem;
import ca.mudar.mtlaucasou.model.jsonapi.HelloApi;
import ca.mudar.mtlaucasou.util.ApiUtils;
......@@ -56,7 +57,7 @@ public class SyncService extends IntentService {
private Realm mRealm;
public static Intent getIntent(Context context) {
public static Intent newIntent(Context context) {
return new Intent(context, SyncService.class);
}
......@@ -85,12 +86,12 @@ public class SyncService extends IntentService {
private void loadInitialLocalData() {
mRealm.beginTransaction();
importLocalData(R.raw.fire_halls, Const.MapTypes.FIRE_HALLS);
importLocalData(R.raw.spvm_stations, Const.MapTypes.SPVM_STATIONS);
importLocalData(R.raw.water_supplies, Const.MapTypes.WATER_SUPPLIES);
importLocalData(R.raw.air_conditioning, Const.MapTypes.WATER_SUPPLIES);
importLocalData(R.raw.emergency_hostels, Const.MapTypes.EMERGENCY_HOSTELS);
importLocalData(R.raw.hospitals, Const.MapTypes.HOSPITALS);
importLocalData(R.raw.fire_halls, Const.MapTypes.FIRE_HALLS, Const.ApiValues.TYPE_FIRE_HALLS);
importLocalData(R.raw.spvm_stations, Const.MapTypes.SPVM_STATIONS, Const.ApiValues.TYPE_SPVM_STATIONS);
importLocalData(R.raw.water_supplies, Const.MapTypes.WATER_SUPPLIES, Const.ApiValues.TYPE_WATER_SUPPLIES);
importLocalData(R.raw.air_conditioning, Const.MapTypes.WATER_SUPPLIES, Const.ApiValues.TYPE_AIR_CONDITIONING);
importLocalData(R.raw.emergency_hostels, Const.MapTypes.EMERGENCY_HOSTELS, Const.ApiValues.TYPE_EMERGENCY_HOSTELS);
importLocalData(R.raw.hospitals, Const.MapTypes.HOSPITALS, Const.ApiValues.TYPE_HOSPITALS);
mRealm.commitTransaction();
}
......@@ -109,9 +110,7 @@ public class SyncService extends IntentService {
final Date updatedAt = dataset.getAttributes().getUpdated();
if (prefs.isApiDataNewer(key, updatedAt)) {
final boolean result = importRemoteData(dataset.getLinks().getSelf(),
dataset.getAttributes().getType());
final boolean result = importRemoteData(dataset);
if (result) {
prefs.setDataUpdatedAt(key, updatedAt);
}
......@@ -124,32 +123,36 @@ public class SyncService extends IntentService {
}
}
private void importLocalData(@RawRes int resource, @MapType String mapType) {
private void importLocalData(@RawRes int resource, @MapType String mapType, String dataType) {
final InputStream inputStream = getResources().openRawResource(resource);
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
final PointsFeatureCollection collection = new Gson()
.fromJson(inputStreamReader, PointsFeatureCollection.class);
RealmQueries.cacheMapData(mRealm, collection.getFeatures(), mapType, false);
RealmQueries.cacheMapData(mRealm, collection.getFeatures(), mapType, dataType, false);
}
/**
* Request the GeoJSON data from the API
*
* @param url The remote dataset URL
* @param mapType The MapType
* @param dataset The dataset to import into the Realm db
* @return
*/
private boolean importRemoteData(String url, @MapType String mapType) {
private boolean importRemoteData(DataItem dataset) {
final Response<PointsFeatureCollection> response = ApiClient
.getPlacemarks(ApiClient.getService(), url);
.getPlacemarks(ApiClient.getService(), dataset.getLinks().getSelf());
if (response != null) {
PointsFeatureCollection collection = response.body();
if (collection != null && collection.getFeatures() != null) {
RealmQueries.clearMapData(mRealm, mapType);
RealmQueries.cacheMapData(mRealm, collection.getFeatures(), mapType, true);
final Attributes attributes = dataset.getAttributes();
RealmQueries.clearMapData(mRealm, attributes.getDataType());
RealmQueries.cacheMapData(mRealm,
collection.getFeatures(),
attributes.getMapType(),
attributes.getDataType(),
true);
}
return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment