/*
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 com.google.android.gms.maps.model.LatLngBounds;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import ca.mudar.mtlaucasou.Const;
import ca.mudar.mtlaucasou.Const.LayerTypes;
import ca.mudar.mtlaucasou.model.LayerType;
import ca.mudar.mtlaucasou.model.MapType;
import ca.mudar.mtlaucasou.model.RealmPlacemark;
import ca.mudar.mtlaucasou.model.geojson.PointsFeature;
import io.realm.Case;
import io.realm.Realm;
import io.realm.RealmQuery;
import io.realm.RealmResults;
import static ca.mudar.mtlaucasou.util.LogUtils.makeLogTag;
public class RealmQueries {
private static final String TAG = makeLogTag("RealmQueries");
private static final Set<String> HEAT_WAVE_LAYERS = new HashSet<>(Arrays.asList(
LayerTypes.AIR_CONDITIONING,
LayerTypes.POOLS,
LayerTypes.WADING_POOLS,
LayerTypes.PLAY_FOUNTAINS));
private static final Set<String> HEALTH_LAYERS = new HashSet<>(Arrays.asList(
LayerTypes.HOSPITALS,
LayerTypes.CLSC));
/**
* Delete data from the Realm db
*
* @param realm
* @param layerType
*/
public static void clearMapData(Realm realm, @LayerType String layerType) {
realm.beginTransaction();
final RealmQuery query = realm.where(RealmPlacemark.class);
if (LayerTypes._HEAT_WAVE_MIXED.equals(layerType)) {
// The `water_supplies` endpoint provides 3 layerTypes we need to delete
query.in(RealmPlacemark.FIELD_LAYER_TYPE, new String[]{
LayerTypes.POOLS,
LayerTypes.WADING_POOLS,
LayerTypes.PLAY_FOUNTAINS
});
} else {
query.equalTo(RealmPlacemark.FIELD_LAYER_TYPE, layerType);
}
query.findAll()
.deleteAllFromRealm();
realm.commitTransaction();
}
/**
* Save the downloaded data to the Realm db
*
* @param realm
* @param pointsFeatures
* @param mapType
* @param layerType
* @param transaction
*/
public static void cacheMapData(Realm realm, List<PointsFeature> pointsFeatures,
@MapType String mapType, @LayerType String layerType,
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(mapType)
.layerType(layerType, feature.getProperties().getType())
.build());
}
if (transaction) {
realm.commitTransaction();
}
}
/**
* Get all Placemarks for requested mapType and selected layers
*
* @param realm
* @param mapType
* @param layers
* @return
*/
public static RealmQuery<RealmPlacemark> queryPlacemarksByMapType(Realm realm,
@MapType String mapType,
@LayerType Set<String> layers) {
final RealmQuery<RealmPlacemark> query = queryPlacemarksByMapType(realm, mapType);
if (layers != null) {
Set<String> filterLayers = null;
if (Const.MapTypes.HEAT_WAVE.equals(mapType)) {
filterLayers = new HashSet<>(HEAT_WAVE_LAYERS);
filterLayers.retainAll(layers);
} else if (Const.MapTypes.HEALTH.equals(mapType)) {
filterLayers = new HashSet<>(HEALTH_LAYERS);
filterLayers.retainAll(layers);
}
if (filterLayers != null && filterLayers.size() > 0) {
return query.in(RealmPlacemark.FIELD_LAYER_TYPE,
filterLayers.toArray(new String[filterLayers.size()]));
}
}
return query;
}
/**
* Get all Placemarks for requested mapType
*
* @param realm
* @param mapType
* @return
*/
private static RealmQuery<RealmPlacemark> queryPlacemarksByMapType(Realm realm, @MapType String mapType) {
return realm
.where(RealmPlacemark.class)
.equalTo(RealmPlacemark.FIELD_MAP_TYPE, mapType);
}
/**
* Filter RealmResults by the visibleRegion bounding box
* Deprecated: not used anymore to allow adding all markers immediately. Limiting the results
* to the bounds means adding multiple markers repeatedly, which blocks the UI thread.
*
* @param query
* @param bounds
* @return
*/
@Deprecated
public static RealmResults<RealmPlacemark> filterPlacemarksQueryByBounds(RealmQuery<RealmPlacemark> query, LatLngBounds bounds) {
return query
.greaterThan(RealmPlacemark.FIELD_COORDINATES_LAT, bounds.southwest.latitude)
.greaterThan(RealmPlacemark.FIELD_COORDINATES_LNG, bounds.southwest.longitude)
.lessThan(RealmPlacemark.FIELD_COORDINATES_LAT, bounds.northeast.latitude)
.lessThan(RealmPlacemark.FIELD_COORDINATES_LNG, bounds.northeast.longitude)
.findAll();
}
/**
* Get all Placemarks with name containing the search-word
*
* @param realm
* @param name
* @return
*/
public static RealmQuery<RealmPlacemark> queryPlacemarksByName(Realm realm, String name) {
return realm
.where(RealmPlacemark.class)
.contains(RealmPlacemark.FIELD_PROPERTIES_NAME, String.valueOf(name), Case.INSENSITIVE);
}
}